implement perspective rays
This commit is contained in:
		
							parent
							
								
									4b8f28f70e
								
							
						
					
					
						commit
						bea7cb5802
					
				| @ -2,14 +2,19 @@ | ||||
| 
 | ||||
| layout (location = 1) uniform vec4 t; | ||||
| 
 | ||||
| layout (location = 2) uniform vec3 w;                       // view space axes | ||||
| layout (location = 3) uniform vec3 u; | ||||
| layout (location = 4) uniform vec3 v; | ||||
| layout (location = 2) uniform vec3 _w;                       // view space axes | ||||
| layout (location = 3) uniform vec3 _u; | ||||
| layout (location = 4) uniform vec3 _v; | ||||
| 
 | ||||
| layout (location = 5) uniform mat4 _cameraInverseProjection; | ||||
| layout (location = 6) uniform vec3 _camh; | ||||
| layout (location = 7) uniform vec3 _camv; | ||||
| layout (location = 8) uniform vec3 _camll; | ||||
| 
 | ||||
| layout(local_size_x = 1, local_size_y = 1) in;              // size of local work group - 1 pixel | ||||
| layout(rgba32f, binding = 0) uniform image2D img_output;    // rgba32f defines internal format, image2d for random write to output texture | ||||
| 
 | ||||
| const float INF = 1000.0f; | ||||
| const float INF = 20.0; | ||||
| 
 | ||||
| #include sphere.glsl | ||||
| 
 | ||||
| @ -24,6 +29,7 @@ struct RayHit | ||||
|     vec3 position; | ||||
|     float distance; | ||||
|     vec3 normal; | ||||
|     vec3 albedo; | ||||
| }; | ||||
| 
 | ||||
| void intersectSphere(Ray ray, inout RayHit bestHit, Sphere sphere) | ||||
| @ -41,13 +47,14 @@ void intersectSphere(Ray ray, inout RayHit bestHit, Sphere sphere) | ||||
|         bestHit.distance = t; | ||||
|         bestHit.position = ray.origin + t*ray.direction; | ||||
|         bestHit.normal = normalize(bestHit.position-sphere.center); | ||||
|         bestHit.albedo = sphere.albedo; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Ray createCameraRay(vec2 uv) | ||||
| { | ||||
|     // transform -1..1 -> 0..1 | ||||
|     //uv = uv*0.5+0.5; | ||||
|     uv = uv*0.5+0.5; | ||||
|     //uv.x=1-uv.x; | ||||
| 
 | ||||
|     // transform camera origin to world space | ||||
| @ -58,12 +65,22 @@ Ray createCameraRay(vec2 uv) | ||||
|     // float2 rd = _CameraLensRadius * randomInUnitDisk(); | ||||
|     // float3 offset = _CameraU * rd.x + _CameraV * rd.y; | ||||
| 
 | ||||
|     // invert perspective projection of view space position | ||||
|     //vec3 dir = mul(_cameraInverseProjection, float4(uv, 0.0, 1.0)).xyz; | ||||
| 
 | ||||
|     // TODO: transform direction from camera to world space (move camera around!) | ||||
| 
 | ||||
|     vec3 dir; | ||||
|     dir = uv.x*_camh + uv.y*_camv; | ||||
|     dir = _camll + uv.x*_camh + uv.y*_camv; | ||||
|     dir = normalize(dir); | ||||
| 
 | ||||
|     float max_x = 5.0; | ||||
|     float max_y = 5.0; | ||||
| 
 | ||||
|     Ray ray; | ||||
|     ray.origin = vec3(uv.x * max_x, uv.y * max_y, 0.0); | ||||
|     ray.direction = vec3(0.0,0.0,1.0);                                          // ortho forwards | ||||
|     ray.origin = vec3(0.0,0.0,0.0); | ||||
|     ray.direction = dir; | ||||
| 
 | ||||
|     return ray; | ||||
| } | ||||
| @ -87,18 +104,33 @@ void main() | ||||
|     hit.position = vec3(0.0,0.0,0.0); | ||||
|     hit.distance = INF; | ||||
|     hit.normal = vec3(0.0,0.0,0.0); | ||||
|     hit.albedo = vec3(0.0,0.0,0.0); | ||||
| 
 | ||||
|     vec3 spheresCenter = _w*-10.0; | ||||
| 
 | ||||
|     Sphere s1; | ||||
|     s1.center = spheresCenter+vec3(sin(t.x),0.0,cos(t.x))*2.5; | ||||
|     s1.radius = 2.0; | ||||
|     s1.albedo = vec3(1.0,0.0,0.0); | ||||
| 
 | ||||
|     Sphere s2; | ||||
|     s2.center = spheresCenter-vec3(sin(t.x),0.0,cos(t.x))*2.5; | ||||
|     s2.radius = 2.0; | ||||
|     s2.albedo = vec3(0.0,0.0,1.0); | ||||
| 
 | ||||
|     Sphere sphere; | ||||
|     //sphere.center = vec3(0.0,0.0,10.0+0.5*t.y); | ||||
|     sphere.center = w*-10.0; | ||||
|     sphere.center = _w*-10.0; | ||||
|     sphere.center += vec3(0.0,0.0,t.y); | ||||
|     sphere.radius = 4.0; | ||||
| 
 | ||||
|     // ray-sphere intersection | ||||
|     intersectSphere(ray, hit, sphere); | ||||
|     intersectSphere(ray, hit, s1); | ||||
|     intersectSphere(ray, hit, s2); | ||||
| 
 | ||||
|     float depth = (hit.distance-6.0)/4.0; | ||||
|     // TODO: write depth to texture | ||||
|     float depth = hit.distance/INF; | ||||
| 
 | ||||
|     pixel = vec4(t.z,1.0-t.z,depth,1.0); | ||||
|     pixel = vec4(hit.albedo,1.0); | ||||
|     pixel *= (1.0-depth); | ||||
| 
 | ||||
|     // output to a specific pixel in the image | ||||
|  | ||||
							
								
								
									
										113
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/main.c
									
									
									
									
									
								
							| @ -1,6 +1,9 @@ | ||||
| #include "main.h" | ||||
| #include "gfx.h" | ||||
| 
 | ||||
| const int WIDTH = 420; | ||||
| const int HEIGHT = 420; | ||||
| 
 | ||||
| // forward declarations
 | ||||
| 
 | ||||
| // input
 | ||||
| @ -9,16 +12,16 @@ int checkQuit(); | ||||
| // time
 | ||||
| float time(); | ||||
| 
 | ||||
| void updateUniforms(GLuint shaderProgram); | ||||
| void updateCameraUniforms(GLuint shaderProgram); | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
|     int width = 420; | ||||
|     int height = 420; | ||||
| 
 | ||||
|     // create a window and opengl context
 | ||||
|     SDL_Window* window = gfxInit(width, height); | ||||
|     SDL_Window* window = gfxInit(WIDTH, HEIGHT); | ||||
| 
 | ||||
|     // create a texture for the compute shader to write to
 | ||||
|     GLuint textureOutput = createWriteOnlyTexture(width, height); | ||||
|     GLuint textureOutput = createWriteOnlyTexture(WIDTH, HEIGHT); | ||||
|     printWorkGroupLimits(); | ||||
| 
 | ||||
|     // compile shader programs
 | ||||
| @ -32,33 +35,15 @@ int main() | ||||
|     initBuffers(); | ||||
|     setVertexAttributes(); | ||||
| 
 | ||||
| 
 | ||||
|     // render loop
 | ||||
|     while (!checkQuit()) | ||||
|     { | ||||
|         glUseProgram(computeProgram); | ||||
| 
 | ||||
|         // update uniforms
 | ||||
|         float t = time();                                           // time
 | ||||
|         float sin_t = sin(t); | ||||
|         int tLocation = glGetUniformLocation(computeProgram, "t"); | ||||
|         glUniform4f(tLocation, t, sin_t, (1.0 + sin_t)*0.5, 0.0f); | ||||
| 
 | ||||
|         // form view space axes
 | ||||
|         vec3 u,v; | ||||
|         vec3 up = {0,1.0,0}; | ||||
|         vec3 w = {0,sin_t*0.1,-1.0}; | ||||
|         glm_vec3_norm(w); | ||||
|         glm_vec3_cross(up,w,u); | ||||
|         glm_vec3_norm(u); | ||||
|         glm_vec3_cross(w, u, v); | ||||
|         int wLocation = glGetUniformLocation(computeProgram, "w"); | ||||
|         glUniform3f(wLocation+0, w[0], w[1], w[2]);                 // w
 | ||||
|         glUniform3f(wLocation+1, u[0], u[1], u[2]);                 // u
 | ||||
|         glUniform3f(wLocation+2, v[0], v[1], v[2]);                 // v
 | ||||
|         updateUniforms(computeProgram); | ||||
| 
 | ||||
|         // dispatch compute shader
 | ||||
|         glDispatchCompute((GLuint)width, (GLuint)height, 1); | ||||
|         glDispatchCompute((GLuint)WIDTH, (GLuint)HEIGHT, 1); | ||||
| 
 | ||||
|         // make sure we're finished writing to the texture before trying to read it
 | ||||
|         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); | ||||
| @ -77,9 +62,85 @@ int main() | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void updateUniforms(GLuint shaderProgram) | ||||
| { | ||||
|     float t = time();                                           // time
 | ||||
|     float sin_t = sin(t); | ||||
|     int tLocation = glGetUniformLocation(shaderProgram, "t"); | ||||
|     glUniform4f(tLocation, t, sin_t, (1.0 + sin_t)*0.5, 0.0f); | ||||
| 
 | ||||
|     updateCameraUniforms(shaderProgram); | ||||
| } | ||||
| 
 | ||||
| void updateCameraUniforms(GLuint shaderProgram) | ||||
| { | ||||
|     // set up perspective projection matrix and its inverse
 | ||||
|     mat4 proj, proji; | ||||
|     float fovy = 60.0;                                          // vertical field of view in deg
 | ||||
|     float near = 0.1; | ||||
|     float far = 1000.0; | ||||
|     float aspect = (float)WIDTH/(float)HEIGHT; | ||||
|     glm_perspective(fovy,aspect,near,far,proj);                 // TODO: radians or degrees??
 | ||||
|     glm_mat4_inv(proj, proji); | ||||
|     int inverseProjLocation = glGetUniformLocation(shaderProgram, "_cameraInverseProjection"); | ||||
|     glUniformMatrix4fv(inverseProjLocation, 1, GL_FALSE, proji[0]); | ||||
| 
 | ||||
|     // form view space axes
 | ||||
|     vec3 u,v; | ||||
|     vec3 up = {0.0,1.0,0.0}; | ||||
|     vec3 w = {0.0,0.0,-1.0}; | ||||
|     glm_vec3_norm(w); | ||||
|     glm_vec3_cross(up,w,u); | ||||
|     glm_vec3_norm(u); | ||||
|     glm_vec3_cross(w, u, v); | ||||
|     int wLocation = glGetUniformLocation(shaderProgram, "_w"); | ||||
|     glUniform3f(wLocation+0, w[0], w[1], w[2]);                 // w
 | ||||
|     glUniform3f(wLocation+1, u[0], u[1], u[2]);                 // u
 | ||||
|     glUniform3f(wLocation+2, v[0], v[1], v[2]);                 // v
 | ||||
| 
 | ||||
|     // get camera properties
 | ||||
|     float theta = glm_rad(fovy);                                    // convert fovy to radians
 | ||||
|     float h = tan(theta*0.5); | ||||
|     float vph = 2.0*h;                                          // viewport height
 | ||||
|     float vpw = aspect*vph;                                     // viewport width
 | ||||
| 
 | ||||
|     // TODO: actual focal length lmao
 | ||||
|     float f = 1.0; | ||||
| 
 | ||||
|     // camera axes
 | ||||
|     //
 | ||||
|     // use vec3_scale instead of vec3_multiply to get scalar multiplication
 | ||||
|     // https://cglm.readthedocs.io/en/latest/vec3.html#c.glm_vec3_scale
 | ||||
|     vec3 camh={0}, | ||||
|          camv={0}, | ||||
|          camll={0}, | ||||
|          camhh={0}, | ||||
|          camvh={0}, | ||||
|          fw={0}; | ||||
| 
 | ||||
|     glm_vec3_scale(u,f*vpw,camh);    | ||||
|     int camhLocation = glGetUniformLocation(shaderProgram, "_camh"); | ||||
|     glUniform3f(camhLocation, camh[0], camh[1], camh[2]); | ||||
|     glm_vec3_scale(v,f*vph,camv); | ||||
|     int camvLocation = camhLocation+1; | ||||
|     glUniform3f(camvLocation, camv[0], camv[1], camv[2]); | ||||
| 
 | ||||
|     // camera lower left corner
 | ||||
|     // calculate half-axes and w*f to establish 3d position of ll corner in camera space
 | ||||
|     glm_vec3_scale(u,f*vpw*0.5,camhh); | ||||
|     glm_vec3_scale(v,f*vph*0.5,camvh); | ||||
|     glm_vec3_scale(w,f,fw); | ||||
|     glm_vec3_sub(camll,camhh,camll); | ||||
|     glm_vec3_sub(camll,camvh,camll); | ||||
|     glm_vec3_sub(camll,fw,camll); | ||||
|     int camllLocation = glGetUniformLocation(shaderProgram, "_camll"); | ||||
|     glUniform3f(camllLocation, camll[0], camll[1], camll[2]); | ||||
| } | ||||
| 
 | ||||
| float time() | ||||
| { | ||||
|     return (float)SDL_GetTicks() / 1000.0f; // ms / 1000.0 = seconds since start
 | ||||
|     // ms / 1000.0 = seconds since start
 | ||||
|     return (float)SDL_GetTicks() / 1000.0f;  | ||||
| } | ||||
| 
 | ||||
| int checkQuit() | ||||
|  | ||||
| @ -2,3 +2,6 @@ | ||||
| 
 | ||||
| #include <cglm/vec3.h> | ||||
| #include <cglm/cam.h> | ||||
| #include <cglm/util.h> | ||||
| 
 | ||||
| #include <math.h> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user