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…
Reference in New Issue