I'm make a 3D space combat game and need to resort to trickery to render planets, moons, and stars to scale. (If only graphic drivers used doubles!) Because the game supports VR I can't use multiple viewports.

I'm inexperienced with shaders, but my understanding so far is that, at least with opengl, the camera is rendered at the origin, and the Model, View, and Projection matrices translates the vertex positions to render correctly on a 2d screen based on world space coordinates.

What I hope is the planet is rendered relative to the camera (due to my scene structure I want to avoid making it a child of the camera), so the planet seems stationary. I guess a type of parallax for a 3D game. I'm not sure how to manipulated the matrices to make this happen.

Here is my shader (converted from a spatialmaterial)

shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : hint_color;
uniform sampler2D texture_albedo : hint_albedo;
uniform float specular;
uniform float metallic;
uniform float roughness : hint_range(0,1);
uniform float point_size : hint_range(0,128);
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;

// Following will be used when orbital mechanics is coded
uniform vec3 relative_position;
uniform float distance = 1;
uniform float size = 1;
uniform float size_km = 5102;


void vertex() {
	UV=UV*uv1_scale.xy+uv1_offset.xy;
    VERTEX.x = VERTEX.x * size_km;
    VERTEX.y = VERTEX.y * size_km;
    VERTEX.z = VERTEX.z * size_km - 13000.0; // Hardcoding to be 13000 km above planet center
    POSITION = PROJECTION_MATRIX *  MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
    // Below are all my failed attempts
    //POSITION = PROJECTION_MATRIX * INV_CAMERA_MATRIX * inverse(WORLD_MATRIX) * vec4(VERTEX, 1.0);
    //POSITION = inverse(PROJECTION_MATRIX) * inverse(MODELVIEW_MATRIX) * vec4(VERTEX, 1.0);
    //POSITION = PROJECTION_MATRIX *  vec4(VERTEX, 1.0);
    //POSITION.z = POSITION.w - 1.0/13000.0;  // Place near z-far.  1/"real" distance from camera to preserve draw order when moons pass in front of planets
    //POSITION.x = POSITION.y - 13000.0;
    //POSITION.w = 1.0;
}


void fragment() {
	vec2 base_uv = UV;
	vec4 albedo_tex = texture(texture_albedo,base_uv);
	ALBEDO = albedo.rgb * albedo_tex.rgb;
	METALLIC = metallic;
	ROUGHNESS = roughness;
	SPECULAR = specular;
}
8 months later

I know this answer comes pretty late, but I think I got working (if I understood what you are trying to do).

I added skip_vertex_transform to the render_mode line, and removed all the matrix stuff, leaving the vertex program like this:

void vertex() {
    UV=UV*uv1_scale.xy+uv1_offset.xy;
    VERTEX.x = VERTEX.x * size_km;
    VERTEX.y = VERTEX.y * size_km;
    VERTEX.z = VERTEX.z * size_km - 13000.0;
}

The camera's far value needs to be very big for anything to show. After this, my mesh was glued to the camera, but then it couldn't rotate or move at all anymore.

Maybe it would be better to just render the background using another viewport.

10 months later