implement perspective rays
This commit is contained in:
parent
4b8f28f70e
commit
bea7cb5802
|
@ -2,14 +2,19 @@
|
||||||
|
|
||||||
layout (location = 1) uniform vec4 t;
|
layout (location = 1) uniform vec4 t;
|
||||||
|
|
||||||
layout (location = 2) uniform vec3 w; // view space axes
|
layout (location = 2) uniform vec3 _w; // view space axes
|
||||||
layout (location = 3) uniform vec3 u;
|
layout (location = 3) uniform vec3 _u;
|
||||||
layout (location = 4) uniform vec3 v;
|
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(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
|
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
|
#include sphere.glsl
|
||||||
|
|
||||||
|
@ -24,6 +29,7 @@ struct RayHit
|
||||||
vec3 position;
|
vec3 position;
|
||||||
float distance;
|
float distance;
|
||||||
vec3 normal;
|
vec3 normal;
|
||||||
|
vec3 albedo;
|
||||||
};
|
};
|
||||||
|
|
||||||
void intersectSphere(Ray ray, inout RayHit bestHit, Sphere sphere)
|
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.distance = t;
|
||||||
bestHit.position = ray.origin + t*ray.direction;
|
bestHit.position = ray.origin + t*ray.direction;
|
||||||
bestHit.normal = normalize(bestHit.position-sphere.center);
|
bestHit.normal = normalize(bestHit.position-sphere.center);
|
||||||
|
bestHit.albedo = sphere.albedo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ray createCameraRay(vec2 uv)
|
Ray createCameraRay(vec2 uv)
|
||||||
{
|
{
|
||||||
// transform -1..1 -> 0..1
|
// transform -1..1 -> 0..1
|
||||||
//uv = uv*0.5+0.5;
|
uv = uv*0.5+0.5;
|
||||||
//uv.x=1-uv.x;
|
//uv.x=1-uv.x;
|
||||||
|
|
||||||
// transform camera origin to world space
|
// transform camera origin to world space
|
||||||
|
@ -58,12 +65,22 @@ Ray createCameraRay(vec2 uv)
|
||||||
// float2 rd = _CameraLensRadius * randomInUnitDisk();
|
// float2 rd = _CameraLensRadius * randomInUnitDisk();
|
||||||
// float3 offset = _CameraU * rd.x + _CameraV * rd.y;
|
// 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_x = 5.0;
|
||||||
float max_y = 5.0;
|
float max_y = 5.0;
|
||||||
|
|
||||||
Ray ray;
|
Ray ray;
|
||||||
ray.origin = vec3(uv.x * max_x, uv.y * max_y, 0.0);
|
ray.origin = vec3(0.0,0.0,0.0);
|
||||||
ray.direction = vec3(0.0,0.0,1.0); // ortho forwards
|
ray.direction = dir;
|
||||||
|
|
||||||
return ray;
|
return ray;
|
||||||
}
|
}
|
||||||
|
@ -87,18 +104,33 @@ void main()
|
||||||
hit.position = vec3(0.0,0.0,0.0);
|
hit.position = vec3(0.0,0.0,0.0);
|
||||||
hit.distance = INF;
|
hit.distance = INF;
|
||||||
hit.normal = vec3(0.0,0.0,0.0);
|
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 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;
|
sphere.radius = 4.0;
|
||||||
|
|
||||||
// ray-sphere intersection
|
// 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);
|
pixel *= (1.0-depth);
|
||||||
|
|
||||||
// output to a specific pixel in the image
|
// output to a specific pixel in the image
|
||||||
|
|
113
src/main.c
113
src/main.c
|
@ -1,6 +1,9 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
|
const int WIDTH = 420;
|
||||||
|
const int HEIGHT = 420;
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
|
|
||||||
// input
|
// input
|
||||||
|
@ -9,16 +12,16 @@ int checkQuit();
|
||||||
// time
|
// time
|
||||||
float time();
|
float time();
|
||||||
|
|
||||||
|
void updateUniforms(GLuint shaderProgram);
|
||||||
|
void updateCameraUniforms(GLuint shaderProgram);
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int width = 420;
|
|
||||||
int height = 420;
|
|
||||||
|
|
||||||
// create a window and opengl context
|
// 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
|
// create a texture for the compute shader to write to
|
||||||
GLuint textureOutput = createWriteOnlyTexture(width, height);
|
GLuint textureOutput = createWriteOnlyTexture(WIDTH, HEIGHT);
|
||||||
printWorkGroupLimits();
|
printWorkGroupLimits();
|
||||||
|
|
||||||
// compile shader programs
|
// compile shader programs
|
||||||
|
@ -32,33 +35,15 @@ int main()
|
||||||
initBuffers();
|
initBuffers();
|
||||||
setVertexAttributes();
|
setVertexAttributes();
|
||||||
|
|
||||||
|
|
||||||
// render loop
|
// render loop
|
||||||
while (!checkQuit())
|
while (!checkQuit())
|
||||||
{
|
{
|
||||||
glUseProgram(computeProgram);
|
glUseProgram(computeProgram);
|
||||||
|
|
||||||
// update uniforms
|
updateUniforms(computeProgram);
|
||||||
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
|
|
||||||
|
|
||||||
// dispatch compute shader
|
// 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
|
// make sure we're finished writing to the texture before trying to read it
|
||||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
|
@ -77,9 +62,85 @@ int main()
|
||||||
return 0;
|
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()
|
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()
|
int checkQuit()
|
||||||
|
|
|
@ -2,3 +2,6 @@
|
||||||
|
|
||||||
#include <cglm/vec3.h>
|
#include <cglm/vec3.h>
|
||||||
#include <cglm/cam.h>
|
#include <cglm/cam.h>
|
||||||
|
#include <cglm/util.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
2
todo.md
2
todo.md
|
@ -9,7 +9,7 @@
|
||||||
* [x] render a texture to a full-screen quad
|
* [x] render a texture to a full-screen quad
|
||||||
* [x] pass uniforms to texture to animate it
|
* [x] pass uniforms to texture to animate it
|
||||||
* [-] ray tracing time
|
* [-] ray tracing time
|
||||||
* [-] perspective
|
* [x] perspective
|
||||||
* [-] depth
|
* [-] depth
|
||||||
* [x] acquire value
|
* [x] acquire value
|
||||||
* [ ] depth texture
|
* [ ] depth texture
|
||||||
|
|
Loading…
Reference in New Issue