Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //=============================================================================================
- // Computer Graphics Sample Program: GPU ray casting
- //=============================================================================================
- #include "framework.h"
- // vertex shader in GLSL
- const char *vertexSource = R"(
- #version 450
- precision highp float;
- uniform vec3 wLookAt, wRight, wUp; // pos of eye
- layout(location = 0) in vec2 cCamWindowVertex; // Attrib Array 0
- out vec3 p;
- void main() {
- gl_Position = vec4(cCamWindowVertex, 0, 1);
- p = wLookAt + wRight * cCamWindowVertex.x + wUp * cCamWindowVertex.y;
- }
- )";
- // fragment shader in GLSL
- const char *fragmentSource = R"(
- #version 450
- precision highp float;
- struct MyRectangle {
- vec3 position;
- vec3 normal;
- float width;
- float height;
- };
- struct Material {
- vec3 ka, kd, ks;
- float shininess;
- vec3 F0;
- int rough, reflective;
- };
- struct Light {
- vec3 direction;
- vec3 Le, La;
- };
- //struct Sphere {
- // vec3 center;
- // float radius;
- //};
- struct Hit {
- float t;
- vec3 position, normal;
- int mat; // material index
- };
- struct Ray {
- vec3 start, dir;
- };
- const int nMaxObjects = 10;
- uniform MyRectangle rects[10];
- uniform vec3 wEye;
- uniform Light light;
- uniform Material materials[2]; // diffuse, specular, ambient ref
- uniform int nObjects;
- in vec3 p; // point on camera window corresponding to the pixel
- out vec4 fragmentColor; // output that goes to the raster memory as told by glBindFragDataLocation
- /*Hit intersect(const Sphere object, const Ray ray) {
- Hit hit;
- hit.t = -1;
- vec3 dist = ray.start - object.center;
- float a = dot(ray.dir, ray.dir);
- float b = dot(dist, ray.dir) * 2.0;
- float c = dot(dist, dist) - object.radius * object.radius;
- float discr = b * b - 4.0 * a * c;
- if (discr < 0)
- return hit;
- float sqrt_discr = sqrt(discr);
- float t1 = (-b + sqrt_discr) / 2.0 / a; // t1 >= t2 for sure
- float t2 = (-b - sqrt_discr) / 2.0 / a;
- if (t1 <= 0)
- return hit;
- hit.t = (t2 > 0) ? t2 : t1;
- hit.position = ray.start + ray.dir * hit.t;
- hit.normal = (hit.position - object.center) / object.radius;
- return hit;
- }*/
- Hit intersect(const MyRectangle object, const Ray ray)
- {
- Hit hit;
- hit.t = -1;
- /* float d = object.normal.x * object.position.x
- + object.normal.y * object.position.y
- + object.normal.z * object.position.z;
- float t = ray.dir.x * object.normal.x
- + ray.dir.y * object.normal.y
- + ray.dir.z * object.normal.z;
- float tnum = d - (ray.start.x * object.normal.x
- + ray.start.y * object.normal.y
- + ray.start.z * object.normal.z);
- float tres = tnum / t;
- hit.position = ray.start.x + ray.dir * tres;*/
- return hit;
- }
- Hit firstIntersect(Ray ray) {
- Hit bestHit;
- bestHit.t = -1;
- for (int o = 0; o < nObjects; o++) {
- Hit hit = intersect(rects[o], ray); // hit.t < 0 if no intersection
- if (o < nObjects/2) hit.mat = 0; // half of the rects are rough
- else hit.mat = 1; // half of the rects are reflective
- if (hit.t > 0 && (bestHit.t < 0 || hit.t < bestHit.t)) bestHit = hit;
- }
- if (dot(ray.dir, bestHit.normal) > 0) bestHit.normal = bestHit.normal * (-1);
- return bestHit;
- }
- bool shadowIntersect(Ray ray) { // for directional lights
- for (int o = 0; o < nObjects; o++) if (intersect(rects[o], ray).t > 0) return true; // hit.t < 0 if no intersection
- return false;
- }
- vec3 Fresnel(vec3 F0, float cosTheta) {
- return F0 + (vec3(1, 1, 1) - F0) * pow(cosTheta, 5);
- }
- const float epsilon = 0.0001f;
- const int maxdepth = 5;
- vec3 trace(Ray ray) {
- vec3 weight = vec3(1, 1, 1);
- vec3 outRadiance = vec3(0, 0, 0);
- for(int d = 0; d < maxdepth; d++) {
- Hit hit = firstIntersect(ray);
- if (hit.t < 0) return weight * light.La;
- if (materials[hit.mat].rough == 1) {
- outRadiance += weight * materials[hit.mat].ka * light.La;
- Ray shadowRay;
- shadowRay.start = hit.position + hit.normal * epsilon;
- shadowRay.dir = light.direction;
- float cosTheta = dot(hit.normal, light.direction);
- if (cosTheta > 0 && !shadowIntersect(shadowRay)) {
- outRadiance += weight * light.Le * materials[hit.mat].kd * cosTheta;
- vec3 halfway = normalize(-ray.dir + light.direction);
- float cosDelta = dot(hit.normal, halfway);
- if (cosDelta > 0) outRadiance += weight * light.Le * materials[hit.mat].ks * pow(cosDelta, materials[hit.mat].shininess);
- }
- }
- if (materials[hit.mat].reflective == 1) {
- weight *= Fresnel(materials[hit.mat].F0, dot(-ray.dir, hit.normal));
- ray.start = hit.position + hit.normal * epsilon;
- ray.dir = reflect(ray.dir, hit.normal);
- } else return outRadiance;
- }
- }
- void main() {
- Ray ray;
- ray.start = wEye;
- ray.dir = normalize(p - wEye);
- fragmentColor = vec4(trace(ray), 1);
- }
- )";
- float cameraX;
- class Material {
- protected:
- vec3 ka, kd, ks;
- float shininess;
- vec3 F0;
- bool rough, reflective;
- public:
- Material RoughMaterial(vec3 _kd, vec3 _ks, float _shininess) {
- ka = _kd * M_PI;
- kd = _kd;
- ks = _ks;
- shininess = _shininess;
- rough = true;
- reflective = false;
- }
- Material SmoothMaterial(vec3 _F0) {
- F0 = _F0;
- rough = false;
- reflective = true;
- }
- void SetUniform(unsigned int shaderProg, int mat) {
- char buffer[256];
- sprintf(buffer, "materials[%d].ka", mat);
- ka.SetUniform(shaderProg, buffer);
- sprintf(buffer, "materials[%d].kd", mat);
- kd.SetUniform(shaderProg, buffer);
- sprintf(buffer, "materials[%d].ks", mat);
- ks.SetUniform(shaderProg, buffer);
- sprintf(buffer, "materials[%d].shininess", mat);
- int location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1f(location, shininess);
- else
- printf("uniform material.shininess cannot be set\n");
- sprintf(buffer, "materials[%d].F0", mat);
- F0.SetUniform(shaderProg, buffer);
- sprintf(buffer, "materials[%d].rough", mat);
- location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1i(location, rough ? 1 : 0);
- else
- printf("uniform material.rough cannot be set\n");
- sprintf(buffer, "materials[%d].reflective", mat);
- location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1i(location, reflective ? 1 : 0);
- else
- printf("uniform material.reflective cannot be set\n");
- }
- };
- class RoughMaterial : public Material {
- public:
- RoughMaterial(vec3 _kd, vec3 _ks, float _shininess) {
- ka = _kd * M_PI;
- kd = _kd;
- ks = _ks;
- shininess = _shininess;
- rough = true;
- reflective = false;
- }
- };
- class SmoothMaterial : public Material {
- public:
- SmoothMaterial(vec3 _F0) {
- F0 = _F0;
- rough = false;
- reflective = true;
- }
- };
- struct Sphere {
- vec3 center;
- float radius;
- Sphere(const vec3& _center, float _radius)
- {
- center = _center;
- radius = _radius;
- }
- void SetUniform(unsigned int shaderProg, int o) {
- char buffer[256];
- sprintf(buffer, "rects[%d].center", o);
- center.SetUniform(shaderProg, buffer);
- sprintf(buffer, "rects[%d].radius", o);
- int location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1f(location, radius);
- else
- printf("uniform %s cannot be set\n", buffer);
- }
- };
- struct MyRectangle
- {
- vec3 position, normal;
- float height, width;
- MyRectangle(const vec3& _position, float _height, float _width)
- {
- position = _position;
- height = _height;
- width = _width;
- vec3 p2 = position;
- p2.x += width;
- vec3 p3 = position;
- p3.y += height;
- vec3 V1 = p2 - position;
- vec3 V2 = p3 - position;
- normal = cross(V1, V2);
- normal = normal * (1.0f / sqrtf((normal.x* normal.x) + (normal.y* normal.y) + (normal.z* normal.z)));
- printf("POSITION: %f %f %f \nNORMAL: %f %f %f\nHEIGHT: %f\nWIDTH: %f\n",
- position.x, position.y, position.z, normal.x, normal.y, normal.z, height, width);
- }
- void SetUniform(unsigned int shaderProg, int o) {
- char buffer[256];
- /* sprintf(buffer, "rects[%d].position", o);
- position.SetUniform(shaderProg, buffer);
- sprintf(buffer, "rects[%d].normal", o);
- normal.SetUniform(shaderProg, buffer);
- sprintf(buffer, "rects[%d].height", o);
- int location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1f(location, height);
- else
- printf("uniform height cannot be set\n");
- */
- sprintf(buffer, "rects[%d].width", o);
- int location = glGetUniformLocation(shaderProg, buffer);
- if (location >= 0)
- glUniform1f(location, width);
- else
- printf("uniform %s cannot be set\n", buffer);
- }
- void print()
- {
- printf("----------------------------------------------------\nPOSITION: %f %f %f \nNORMAL: %f %f %f\nHEIGHT: %f\nWIDTH: %f\n-------------------------------------------------",
- position.x, position.y, position.z, normal.x, normal.y, normal.z, height, width);
- }
- };
- class Camera {
- vec3 eye, lookat, right, up;
- float fov;
- public:
- void set(vec3 _eye, vec3 _lookat, vec3 vup, double _fov) {
- eye = _eye;
- lookat = _lookat;
- fov = _fov;
- vec3 w = eye - lookat;
- float f = length(w);
- right = normalize(cross(vup, w)) * f * tan(fov / 2);
- up = normalize(cross(w, right)) * f * tan(fov / 2);
- }
- void Animate(float dt) {
- eye = vec3((eye.x - lookat.x) * cos(dt) + (eye.z - lookat.z) * sin(dt) + lookat.x,
- eye.y,
- -(eye.x - lookat.x) * sin(dt) + (eye.z - lookat.z) * cos(dt) + lookat.z);
- set(eye, lookat, up, fov);
- }
- void SetUniform(unsigned int shaderProg) {
- eye.SetUniform(shaderProg, "wEye");
- lookat.SetUniform(shaderProg, "wLookAt");
- right.SetUniform(shaderProg, "wRight");
- up.SetUniform(shaderProg, "wUp");
- }
- };
- struct Light {
- vec3 direction;
- vec3 Le, La;
- Light(vec3 _direction, vec3 _Le, vec3 _La) {
- direction = normalize(_direction);
- Le = _Le; La = _La;
- }
- void SetUniform(unsigned int shaderProg) {
- La.SetUniform(shaderProg, "light.La");
- Le.SetUniform(shaderProg, "light.Le");
- direction.SetUniform(shaderProg, "light.direction");
- }
- };
- float rnd() { return (float)rand() / RAND_MAX; }
- class Scene {
- std::vector<MyRectangle*> rects;
- std::vector<Light *> lights;
- Camera camera;
- std::vector<Material *> materials;
- public:
- void build() {
- vec3 eye = vec3(0, 0, 2);
- vec3 vup = vec3(0, 1, 0);
- vec3 lookat = vec3(0, 0, 0);
- float fov = 45 * M_PI / 180;
- camera.set(eye, lookat, vup, fov);
- lights.push_back(new Light(vec3(1, 1, 1), vec3(3, 3, 3), vec3(0.4, 0.3, 0.3)));
- vec3 kd(0.3f, 0.2f, 0.1f), ks(10, 10, 10);
- for (int i = 0; i < 10; i++)
- rects.push_back(new MyRectangle(vec3(rnd() - 0.5, rnd() - 0.5, rnd() - 0.5), 2.0f, 0.5f));
- for (size_t i = 0; i < 10; i++)
- {
- rects[i]->print();
- }
- materials.push_back(new RoughMaterial(kd, ks, 50));
- materials.push_back(new SmoothMaterial(vec3(0.9, 0.85, 0.8)));
- }
- void SetUniform(unsigned int shaderProg) {
- int location = glGetUniformLocation(shaderProg, "nObjects");
- if (location >= 0)
- glUniform1i(location, rects.size());
- else
- printf("uniform nObjects cannot be set\n");
- for (int o = 0; o < rects.size(); o++)
- rects[o]->SetUniform(shaderProg, o);
- lights[0]->SetUniform(shaderProg);
- camera.SetUniform(shaderProg);
- for (int mat = 0; mat < materials.size(); mat++)
- materials[mat]->SetUniform(shaderProg, mat);
- }
- void Animate(float dt) { camera.Animate(dt); }
- };
- GPUProgram gpuProgram; // vertex and fragment shaders
- Scene scene;
- class FullScreenTexturedQuad {
- unsigned int vao; // vertex array object id and texture id
- public:
- void Create() {
- glGenVertexArrays(1, &vao); // create 1 vertex array object
- glBindVertexArray(vao); // make it active
- unsigned int vbo; // vertex buffer rects
- glGenBuffers(1, &vbo); // Generate 1 vertex buffer rects
- // vertex coordinates: vbo0 -> Attrib Array 0 -> vertexPosition of the vertex shader
- glBindBuffer(GL_ARRAY_BUFFER, vbo); // make it active, it is an array
- float vertexCoords[] = { -1, -1, 1, -1, 1, 1, -1, 1 }; // two triangles forming a quad
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoords), vertexCoords, GL_STATIC_DRAW); // copy to that part of the memory which is not modified
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); // stride and offset: it is tightly packed
- }
- void Draw() {
- glBindVertexArray(vao); // make the vao and its vbos active playing the role of the data source
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // draw two triangles forming a quad
- }
- };
- class Line
- {
- public:
- int size = 4;
- float vertices[4];
- float color[3];
- float xShift = 0.0f;
- float yShift = 0.0f;
- float rShift = 0.0f;
- unsigned int vao;
- unsigned int vbo;
- float x;
- float y;
- float x2;
- float y2;
- Line() {}
- void SetShift(float X, float Y)
- {
- xShift = X;
- yShift = Y;
- }
- void SetColor(float r, float g, float b)
- {
- color[0] = r;
- color[1] = g;
- color[2] = b;
- }
- void LoadVertices(float X1, float Y1, float X2, float Y2)
- {
- x = X1;
- y = Y1;
- x2 = X2;
- y2 = Y2;
- vertices[0] = x;
- vertices[1] = y;
- vertices[2] = x2;
- vertices[3] = y2;
- }
- void Create()
- {
- glGenVertexArrays(1, &vao); // create 1 vertex array object
- glBindVertexArray(vao); // make it active
- glGenBuffers(1, &vbo); // Generate 1 buffer
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- // Geometry with 24 bytes (6 floats or 3 x 2 coordinates)
- glBufferData(GL_ARRAY_BUFFER, // Copy to GPU target
- sizeof(vertices), // # bytes
- &vertices, // address
- GL_STATIC_DRAW); // we do not change later
- glEnableVertexAttribArray(0); // AttribArray 0
- glVertexAttribPointer(0, // vbo -> AttribArray 0
- 2, GL_FLOAT, GL_FALSE, // two floats/attrib, not fixed-point
- 0, NULL); // stride, offset: tightly packed
- }
- void Draw()
- {
- int location;
- // Set color to (0, 1, 0) = green
- location = glGetUniformLocation(gpuProgram.getId(), "color");
- glUniform3f(location, color[0], color[1], color[2]); // 3 floats
- float MVPtransf[4][4] = { (float)cos(rShift), -(float)sin(rShift), 0, 0, // MVP matrix,
- (float)sin(rShift), (float)cos(rShift), 0, 0, // row-major!
- 0, 0, 1, 0,
- xShift + cameraX, yShift, 0, 1 };
- location = glGetUniformLocation(gpuProgram.getId(), "MVP"); // Get the GPU location of uniform variable MVP
- glUniformMatrix4fv(location, 1, GL_TRUE, &MVPtransf[0][0]); // Load a 4x4 row-major float matrix to the specified location
- glBindVertexArray(vao); // Draw call
- glDrawArrays(GL_LINE_STRIP, 0 /*startIdx*/, size / 2 /*# Elements*/);
- }
- void Animate(float t)
- {
- rShift = t;
- }
- };
- class DynamicPolygon
- {
- unsigned int vao;
- unsigned int vbo[2];
- float sidelength = 0.50f;
- float xShift = 0;
- float yShift = 0;
- int size = 3;
- float rotation = 0.0f;
- float color[3] = { 1,1,1 };
- float *vertices;
- public:
- DynamicPolygon() {}
- void LoadVertices(float x, float y, float R)
- {
- delete[]vertices;
- vertices = new float[size * 2];
- for (int i = 0; i < size * 2; i += 2)
- {
- float angle = float(i) / size * float(M_PI);
- float x_ = x + (cos(angle) * R);
- float y_ = y + (sin(angle) * R);
- vertices[i] = x_;
- vertices[i + 1] = y_;
- }
- }
- void Create()
- {
- LoadVertices(0, 0, sidelength);
- glGenVertexArrays(1, &vao); // create 1 vertex array object
- glBindVertexArray(vao); // make it active
- unsigned int vbo[2]; // vertex buffer rects
- glGenBuffers(2, &vbo[0]); // Generate 2 vertex buffer rects
- // vertex coordinates: vbo[0] -> Attrib Array 0 -> vertexPosition of the vertex shader
- glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // make it active, it is an array
- glBufferData(GL_ARRAY_BUFFER, // copy to the GPU
- sizeof(float) * 2 * size, // number of the vbo in bytes
- vertices, // address of the data array on the CPU
- GL_DYNAMIC_DRAW); // copy to that part of the memory which is not modified
- // Map Attribute Array 0 to the current bound vertex buffer (vbo[0])
- glEnableVertexAttribArray(0);
- // Data organization of Attribute Array 0
- glVertexAttribPointer(0, // Attribute Array 0
- 2, GL_FLOAT, // components/attribute, component type
- GL_FALSE, // not in fixed point format, do not normalized
- 0, NULL); // stride and offset: it is tightly packed
- // vertex colors: vbo[1] -> Attrib Array 1 -> vertexColor of the vertex shader
- glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); // make it active, it is an array
- float vertexColors[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; // vertex data on the CPU
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertexColors), vertexColors, GL_DYNAMIC_DRAW); // copy to the GPU
- // Map Attribute Array 1 to the current bound vertex buffer (vbo[1])
- glEnableVertexAttribArray(1); // Vertex position
- // Data organization of Attribute Array 1
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL); // Attribute Array 1, components/attribute, component type, normalize?, tightly packed
- }
- void Draw() {
- int location;
- // Set color to (0, 1, 0) = green
- mat4 MVPtransf = { (float)cos(rotation), -(float)sin(rotation), 0, 0, // MVP matrix,
- (float)sin(rotation), (float)cos(rotation), 0, 0, // row-major!
- 0, 0, 1, 0,
- xShift + cameraX, yShift, 0, 1 };
- location = glGetUniformLocation(gpuProgram.getId(), "MVP"); // Get the GPU location of uniform variable MVP
- glUniformMatrix4fv(location, 1, GL_TRUE, &MVPtransf.m[0][0]); // Load a 4x4 row-major float matrix to the specified location
- glBindVertexArray(vao); // Draw call
- glDrawArrays(GL_TRIANGLE_FAN, 0 /*startIdx*/, size /*# Elements*/);
- }
- void IncreaseSides()
- {
- size++;
- Create();
- }
- void Animate(float t)
- {
- rotation = t;
- }
- };
- DynamicPolygon p;
- FullScreenTexturedQuad fullScreenTexturedQuad;
- // Initialization, create an OpenGL context
- void onInitialization() {
- glViewport(0, 0, windowWidth, windowHeight);
- scene.build();
- fullScreenTexturedQuad.Create();
- // create program for the GPU
- gpuProgram.Create(vertexSource, fragmentSource, "fragmentColor");
- gpuProgram.Use();
- }
- // Window has become invalid: Redraw
- void onDisplay() {
- static int nFrames = 0;
- nFrames++;
- static long tStart = glutGet(GLUT_ELAPSED_TIME);
- long tEnd = glutGet(GLUT_ELAPSED_TIME);
- printf("%d msec\r", (tEnd - tStart) / nFrames);
- glClearColor(1.0f, 0.5f, 0.8f, 1.0f); // background color
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the screen
- scene.SetUniform(gpuProgram.getId());
- fullScreenTexturedQuad.Draw();
- glutSwapBuffers(); // exchange the two buffers
- }
- // Key of ASCII code pressed
- void onKeyboard(unsigned char key, int pX, int pY) {
- }
- // Key of ASCII code released
- void onKeyboardUp(unsigned char key, int pX, int pY) {
- }
- // Mouse click event
- void onMouse(int button, int state, int pX, int pY) {
- }
- // Move mouse with key pressed
- void onMouseMotion(int pX, int pY) {
- }
- // Idle event indicating that some time elapsed: do animation here
- void onIdle() {
- scene.Animate(0.01f);
- glutPostRedisplay();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement