diff options
| author | Patrick | 2021-03-23 19:28:28 +0100 |
|---|---|---|
| committer | Patrick | 2021-03-23 19:28:28 +0100 |
| commit | a0fdc6d882a1755d0b0607ba3d9bb55e7f8ac006 (patch) | |
| tree | 82aab3828111378b6f0421aa58025b43f98f13a2 | |
| parent | cedffd5cf24c1a3ed64161475c806c55135406be (diff) | |
| download | subsurface_scattering-a0fdc6d882a1755d0b0607ba3d9bb55e7f8ac006.tar.gz subsurface_scattering-a0fdc6d882a1755d0b0607ba3d9bb55e7f8ac006.zip | |
fix translucency, add gaussian blur to shader
| -rw-r--r-- | build.sh | 6 | ||||
| -rw-r--r-- | shaders/fbo_frag.glsl | 39 | ||||
| -rw-r--r-- | shaders/frag_irradiance.glsl | 25 | ||||
| -rw-r--r-- | shaders/frag_shadowmap.glsl | 9 | ||||
| -rw-r--r-- | shaders/vert_irradiance.glsl | 77 | ||||
| -rw-r--r-- | shaders/vert_shadowmap.glsl (renamed from shaders/vert.glsl) | 6 | ||||
| -rw-r--r-- | src/main.cpp | 107 | ||||
| -rw-r--r-- | src/main2.cpp | 656 |
8 files changed, 879 insertions, 46 deletions
@@ -1,2 +1,4 @@ -# g++ -c ~/cpp/libs/imgui/*.cpp ~/cpp/libs/imgui-sfml/*.cpp -I ~/cpp/libs/imgui -I ~/cpp/libs/imgui-sfml/ -g++ src/main.cpp ./*.o -o main -I ~/cpp/libs/imgui -I ~/cpp/libs/imgui-sfml -lsfml-system -lsfml-window -lsfml-graphics -lGLEW -lGL -lassimp +#!/bin/sh + +# g++ -c C:/prg/cpp/libs/imgui/*.cpp C:/prg/cpp/libs/imgui-sfml/*.cpp -I C:/prg/cpp/libs/imgui -I C:/prg/cpp/libs/imgui-sfml -I C:/prg/cpp/libs/SFML-2.5.1/include +g++ src/main.cpp ./bin/*.o -o main -I C:/prg/cpp/libs/SFML-2.5.1/include -I C:/prg/cpp/libs/assimp-5.0.1/include -I C:/prg/cpp/libs/assimp-5.0.1/build/include -I C:/prg/cpp/libs/glew-2.1.0/include -I C:/prg/cpp/libs/glm -I C:/prg/cpp/libs/imgui -I C:/prg/cpp/libs/imgui-sfml -L "C:/prg/cpp/libs/SFML-2.5.1/build/lib/Release" -L "C:/prg/cpp/libs/assimp-5.0.1/build/code/Release" -L "C:/prg/cpp/libs/glew-2.1.0/lib/Release/x64" -lsfml-system -lsfml-window -lsfml-graphics -lGLEW -lGL -lassimp diff --git a/shaders/fbo_frag.glsl b/shaders/fbo_frag.glsl index 7463fc8..1102992 100644 --- a/shaders/fbo_frag.glsl +++ b/shaders/fbo_frag.glsl @@ -11,24 +11,51 @@ uniform int renderState; uniform vec2 samplePositions[13];
uniform vec3 sampleWeights[13];
+vec4 blur(sampler2D tex, vec2 uv, vec2 res) {
+ float Pi = 6.28318530718; // Pi*2
+
+ // GAUSSIAN BLUR SETTINGS {{{
+ float Directions = 16.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
+ float Quality = 4.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
+ float Size = 8.0; // BLUR SIZE (Radius)
+ // GAUSSIAN BLUR SETTINGS }}}
+
+ vec2 Radius = Size/res;
+
+ // Pixel colour
+ vec4 Color = texture(tex, uv);
+
+ // Blur calculations
+ for( float d=0.0; d<Pi; d+=Pi/Directions) {
+ for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality) {
+ Color += texture( tex, uv+vec2(cos(d),sin(d))*Radius*i);
+ }
+ }
+
+ // Output to screen
+ Color /= Quality * Directions - 15.0;
+ return Color;
+}
+
void main()
{
if (renderState == 0) {
- FragColor = texture(shadowmapTexture, TexCoords);
+ FragColor = blur(shadowmapTexture, TexCoords, vec2(screenWidth, screenHeight));
}
- // stencil buffer
else if (renderState == 1) {
- FragColor = texture(irradianceTexture, TexCoords);
+ FragColor = texture(shadowmapTexture, TexCoords);
}
+ // stencil buffer
else if (renderState == 2) {
- FragColor = texture(shadowmapTexture, TexCoords) * texture(irradianceTexture, TexCoords);
+ FragColor = texture(irradianceTexture, TexCoords);
}
else if (renderState == 3) {
vec4 result = vec4(0, 0, 0, 1);
for (int i = 0; i < 13; i++) {
vec2 sampleCoords = TexCoords + samplePositions[i] * vec2(1.0/screenWidth, 1.0/screenHeight);
- vec4 sample = texture(irradianceTexture, sampleCoords)
- * texture(shadowmapTexture, sampleCoords);
+ //vec4 sample = texture(irradianceTexture, sampleCoords)
+ // * texture(shadowmapTexture, sampleCoords);
+ vec4 sample = texture(irradianceTexture, sampleCoords);
vec4 weight = vec4(sampleWeights[i], 1);
result += sample * weight;
}
diff --git a/shaders/frag_irradiance.glsl b/shaders/frag_irradiance.glsl index 9e14ebe..497bdf0 100644 --- a/shaders/frag_irradiance.glsl +++ b/shaders/frag_irradiance.glsl @@ -1,16 +1,21 @@ #version 330 core
in vec3 FragPos;
+in vec3 LocalPos;
+in vec3 Backside;
+in float BacksideIrradiance;
in vec3 Normal;
out vec4 FragColor;
-uniform sampler2D shadowmapTexture;
-
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
+uniform float transmittanceScale;
+uniform int renderState;
+uniform float powBase;
+uniform float powFactor;
void main()
{
@@ -29,6 +34,22 @@ void main() float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
+ //float distanceToBackside = length(clamp(FragPos - Backside, vec3(0), vec3(1000)));
+ float distanceToBackside = length(FragPos - Backside);
+ //distanceToBackside = distance(Backside, LocalPos);
vec3 result = (ambient + diffuse + specular) * objectColor;
+
+ if (renderState == 3)
+ if (distanceToBackside != 0)
+ //result += objectColor * pow(powBase, -pow(distanceToBackside, 2)) * transmittanceScale * (1 - diff);
+ result += objectColor * pow(powBase, powFactor / pow(distanceToBackside, 0.6)) * transmittanceScale * (1 - diff);
+ // if (renderState == 3) {
+ // //result = Backside;
+ // //result = LocalPos;
+ // result = vec3(distanceToBackside);
+ // }
+
+
FragColor = vec4(result, 1.0f);
+ //FragColor = vec4(vec3(distanceToBackside), 1);
}
diff --git a/shaders/frag_shadowmap.glsl b/shaders/frag_shadowmap.glsl index 6d6dab6..9a15c7a 100644 --- a/shaders/frag_shadowmap.glsl +++ b/shaders/frag_shadowmap.glsl @@ -2,6 +2,7 @@ #version 330 core
in vec3 FragPos;
+in vec3 LocalPos;
out vec4 FragColor;
@@ -9,6 +10,10 @@ uniform vec3 lightPos; void main()
{
- float lightDist = 1 - (length(lightPos - FragPos) - 5.5);
- FragColor = vec4(vec3(lightDist), 1);
+ float lightDist = length(lightPos - FragPos);
+ float c1 = mod(lightDist, 10);
+ float c2 = mod(lightDist/10, 10);
+ float c3 = mod(lightDist/100, 10);
+ FragColor = vec4(c1, c2, c3, 1);
+ //FragColor = vec4(LocalPos/10, 1);
}
diff --git a/shaders/vert_irradiance.glsl b/shaders/vert_irradiance.glsl new file mode 100644 index 0000000..25770f6 --- /dev/null +++ b/shaders/vert_irradiance.glsl @@ -0,0 +1,77 @@ +#version 330 core
+
+layout (location = 0) in vec3 pos;
+layout (location = 1) in vec3 normal;
+
+out vec3 FragPos;
+out vec3 LocalPos;
+out vec3 Backside;
+out float BacksideIrradiance;
+out vec3 Normal;
+
+uniform sampler2D shadowmapTexture;
+uniform vec3 lightPos;
+uniform vec2 samplePositions[13];
+uniform vec3 sampleWeights[13];
+uniform int screenWidth;
+uniform int screenHeight;
+
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 lightView;
+uniform mat4 lightViewInv;
+uniform mat4 projection;
+uniform mat4 lightProjection;
+
+vec4 blur(sampler2D tex, vec2 uv, vec2 res) {
+ float Pi = 6.28318530718; // Pi*2
+
+ // GAUSSIAN BLUR SETTINGS {{{
+ float Directions = 16.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
+ float Quality = 4.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
+ float Size = 8.0; // BLUR SIZE (Radius)
+ // GAUSSIAN BLUR SETTINGS }}}
+
+ vec2 Radius = Size/res;
+
+ // Pixel colour
+ vec4 Color = texture(tex, uv);
+
+ // Blur calculations
+ for( float d=0.0; d<Pi; d+=Pi/Directions) {
+ for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality) {
+ Color += texture( tex, uv+vec2(cos(d),sin(d))*Radius*i);
+ }
+ }
+
+ // Output to screen
+ Color /= Quality * Directions - 15.0;
+ return Color;
+}
+
+void main()
+{
+ gl_Position = projection * view * model * vec4(pos, 1.0);
+ FragPos = vec3(model * vec4(pos, 1));
+ LocalPos = pos;
+ Normal = normal;
+
+ vec4 lightSpace = lightProjection * lightView * model * vec4(pos, 1.0);
+ lightSpace = lightSpace / lightSpace.w;
+ vec2 shadowmapCoords = lightSpace.xy;
+ shadowmapCoords = vec2(
+ (shadowmapCoords.x * 0.99 + 1) / 2,
+ (shadowmapCoords.y * 0.99 + 1) / 2
+ );
+
+
+ // blur
+ vec4 t = texture(shadowmapTexture, shadowmapCoords);
+ //vec4 t = blur(shadowmapTexture, shadowmapCoords, vec2(screenWidth, screenHeight));
+
+ BacksideIrradiance = t.r + t.g*10 + t.b*100;
+
+ vec3 lightDir = (vec3(0, 0, 0) - lightPos);
+ Backside = (lightPos + (lightDir * BacksideIrradiance));
+ //Backside = texture(shadowmapTexture, shadowmapCoords).xyz*10;
+}
diff --git a/shaders/vert.glsl b/shaders/vert_shadowmap.glsl index 6f48573..50847bb 100644 --- a/shaders/vert.glsl +++ b/shaders/vert_shadowmap.glsl @@ -4,15 +4,17 @@ layout (location = 0) in vec3 pos; layout (location = 1) in vec3 normal;
out vec3 FragPos;
+out vec3 LocalPos;
out vec3 Normal;
uniform mat4 model;
-uniform mat4 view;
+uniform mat4 lightView;
uniform mat4 projection;
void main()
{
- gl_Position = projection * view * model * vec4(pos, 1.0);
+ gl_Position = projection * lightView * model * vec4(pos, 1.0);
FragPos = vec3(model * vec4(pos, 1));
+ LocalPos = pos;
Normal = normal;
}
diff --git a/src/main.cpp b/src/main.cpp index dde29ec..24a39cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,8 +23,13 @@ /*
TODO:
-- ShadowMap to fbo
- Save Depth to fbo
+- Stencil Buffer
+- LightDist > 1
+ - 1 - distanceToBackside in frag_irradiance
+- ShadowMap Perspective (no projection?)
+- (Implement Gaussian Blur)
+- LightDir nicht immer zu 0 0 0
*/
@@ -101,7 +106,6 @@ private: GLuint VAO = 0;
};
-
struct freecam {
glm::vec3 pos = glm::vec3(0, 0, -1);
glm::vec2 rot = glm::vec2(0, 0);
@@ -155,7 +159,6 @@ private: float moveFactor = 20;
};
-
struct arccam {
glm::vec2 rot = glm::vec2(0, 0);
float radius = 1;
@@ -207,7 +210,6 @@ private: const float angleFactor = 200;
};
-
std::string readFile(std::string filename) {
std::ifstream ifs(filename, std::ios::binary);
std::string result, line;
@@ -222,19 +224,22 @@ model loadModel(const std::string &filename) { const aiScene *scene = importer.ReadFile(
filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |
- aiProcess_SortByPType | aiProcess_GenSmoothNormals);
+ aiProcess_SortByPType | aiProcess_GenSmoothNormals |
+ aiProcess_GenUVCoords);
model result;
+ printf("uv channels: %d\n", scene->mMeshes[0]->GetNumUVChannels());
+
for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {
aiVector3D v = scene->mMeshes[0]->mVertices[i];
aiVector3D n = scene->mMeshes[0]->mNormals[i];
- result.vertices.push_back(v.x);
- result.vertices.push_back(v.y);
- result.vertices.push_back(v.z);
- result.vertices.push_back(n.x);
- result.vertices.push_back(n.y);
- result.vertices.push_back(n.z);
+ result.vertices.push_back(v.x * 100);
+ result.vertices.push_back(v.y * 100);
+ result.vertices.push_back(v.z * 100);
+ result.vertices.push_back(n.x * 100);
+ result.vertices.push_back(n.y * 100);
+ result.vertices.push_back(n.z * 100);
}
for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {
@@ -293,7 +298,6 @@ GLuint compileShaders(const char *vertFilename, const char *fragFilename) { return shaderProgram;
}
-
struct framebuffer {
framebuffer(const char *vertFilename, const char *fragFilename, int width, int height) {
glGenFramebuffers(1, &fbo);
@@ -387,23 +391,23 @@ int main() { if (glewInit() != GLEW_OK) {
}
- GLuint shaderProgramShadowmap = compileShaders("shaders/vert.glsl", "shaders/frag_shadowmap.glsl");
- GLuint shaderProgramIrradiance = compileShaders("shaders/vert.glsl", "shaders/frag_irradiance.glsl");
+ GLuint shaderProgramShadowmap = compileShaders("shaders/vert_shadowmap.glsl", "shaders/frag_shadowmap.glsl");
+ GLuint shaderProgramIrradiance = compileShaders("shaders/vert_irradiance.glsl", "shaders/frag_irradiance.glsl");
- model m = loadModel("models/Isotrop-upperjaw.ply");
+ //model m = loadModel("models/Isotrop-upperjaw.ply");
+ model m = loadModel("models/african_head/african_head.obj");
arccam arcCam;
freecam freeCam;
-
- glm::vec3 lightPos(1.2f, 5.0f, 2.0f);
// MVP
glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));
- glm::mat4 view;
+ glm::mat4 view, lightView;
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);
+ glm::mat4 lightProj = glm::perspective(glm::radians(90.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);
// Framebuffer
framebuffer fb_shadowmap("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);
@@ -411,12 +415,18 @@ int main() { // Config
- struct {
+ const struct {
bool wireframe = false;
bool freecam = false;
- int renderState = 0;
+ int renderState = 2;
float color[3] = { 0.7f, 0.4f, 0.4f };
- } options;
+ glm::vec3 lightPos = glm::vec3(0.0f, 0.04f, -0.08f);
+ float transmittanceScale = 0.005f;
+ float powBase = 2.718;
+ float powFactor = 1;
+ } DefaultOptions;
+
+ auto options = DefaultOptions;
sf::Clock deltaClock;
@@ -473,6 +483,10 @@ int main() { // Render Shadowmap
+ glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
+ glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
+ glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
+
glBindFramebuffer(GL_FRAMEBUFFER, fb_shadowmap.fbo);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -490,19 +504,21 @@ int main() { else
view = arcCam.getViewMatrix();
+ lightView = glm::lookAt(options.lightPos, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
+
glUniformMatrix4fv(
glGetUniformLocation(shaderProgramShadowmap, "model"),
1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(
- glGetUniformLocation(shaderProgramShadowmap, "view"),
- 1, GL_FALSE, glm::value_ptr(view));
+ glGetUniformLocation(shaderProgramShadowmap, "lightView"),
+ 1, GL_FALSE, glm::value_ptr(lightView));
glUniformMatrix4fv(
glGetUniformLocation(shaderProgramShadowmap, "projection"),
- 1, GL_FALSE, glm::value_ptr(proj));
+ 1, GL_FALSE, glm::value_ptr(lightProj));
glUniform3fv(
glGetUniformLocation(shaderProgramShadowmap, "lightPos"),
- 1, glm::value_ptr(lightPos));
+ 1, glm::value_ptr(options.lightPos));
m.draw();
@@ -520,11 +536,6 @@ int main() { glUseProgram(shaderProgramIrradiance);
- if (options.freecam)
- view = freeCam.getViewMatrix();
- else
- view = arcCam.getViewMatrix();
-
glUniformMatrix4fv(
glGetUniformLocation(shaderProgramIrradiance, "model"),
1, GL_FALSE, glm::value_ptr(model));
@@ -532,8 +543,34 @@ int main() { glGetUniformLocation(shaderProgramIrradiance, "view"),
1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightView"),
+ 1, GL_FALSE, glm::value_ptr(lightView));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightViewInv"),
+ 1, GL_FALSE, glm::value_ptr(glm::inverse(lightView)));
+ glUniformMatrix4fv(
glGetUniformLocation(shaderProgramIrradiance, "projection"),
1, GL_FALSE, glm::value_ptr(proj));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightProjection"),
+ 1, GL_FALSE, glm::value_ptr(lightProj));
+ glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenWidth"), window.getSize().x);
+ glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenHeight"), window.getSize().y);
+ glUniform2fv(glGetUniformLocation(shaderProgramIrradiance, "samplePositions"), 13, samplePositions);
+ glUniform3fv(glGetUniformLocation(shaderProgramIrradiance, "sampleWeights"), 13, sampleWeights);
+
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "transmittanceScale"),
+ options.transmittanceScale);
+ glUniform1i(
+ glGetUniformLocation(shaderProgramIrradiance, "renderState"),
+ options.renderState);
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "powBase"),
+ options.powBase);
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "powFactor"),
+ options.powFactor);
glUniform3fv(
glGetUniformLocation(shaderProgramIrradiance, "objectColor"),
@@ -543,7 +580,7 @@ int main() { 1.0f, 1.0f, 1.0f);
glUniform3fv(
glGetUniformLocation(shaderProgramIrradiance, "lightPos"),
- 1, glm::value_ptr(lightPos));
+ 1, glm::value_ptr(options.lightPos));
glUniform3fv(
glGetUniformLocation(shaderProgramIrradiance, "viewPos"),
1, glm::value_ptr(options.freecam ? freeCam.pos : arcCam.getPos()));
@@ -586,13 +623,18 @@ int main() { ImGui::Checkbox("Wireframe", &options.wireframe);
ImGui::Checkbox("Free Cam", &options.freecam);
ImGui::InputInt("Render State", &options.renderState);
- ImGui::InputFloat3("Color", options.color, 2);
+ ImGui::DragFloat3("Color", options.color, 0.01, 0, 1);
+ ImGui::DragFloat("Transmittance Scale", &options.transmittanceScale, 0.0001f, 0, 0.3);
+ ImGui::DragFloat("Pow Base", &options.powBase, 0.01f, 0, 4);
+ ImGui::DragFloat("Pow Factor", &options.powFactor, 0.01f, 0, 3);
+ ImGui::DragFloat3("Light Pos", glm::value_ptr(options.lightPos), 0.01, -5, 5);
if (options.freecam) {
ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);
ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);
if (ImGui::Button("Reset")) {
freeCam.pos = glm::vec3(0, 0, -1);
freeCam.rot = glm::vec2(0);
+ options = DefaultOptions;
}
} else {
ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);
@@ -600,6 +642,7 @@ int main() { if (ImGui::Button("Reset")) {
arcCam.rot = glm::vec2(0);
arcCam.radius = 1;
+ options = DefaultOptions;
}
}
ImGui::End();
diff --git a/src/main2.cpp b/src/main2.cpp new file mode 100644 index 0000000..24a39cc --- /dev/null +++ b/src/main2.cpp @@ -0,0 +1,656 @@ +#include <stdio.h>
+#include <fstream>
+
+#include <GL/glew.h>
+
+#define GLM_ENABLE_EXPERIMENTAL
+
+#include <glm/glm.hpp>
+#include <glm/gtx/rotate_vector.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+
+#include <SFML/OpenGL.hpp>
+#include <SFML/Graphics.hpp>
+
+#include <imgui.h>
+#include <imgui-SFML.h>
+
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+
+/*
+
+TODO:
+- Save Depth to fbo
+- Stencil Buffer
+- LightDist > 1
+ - 1 - distanceToBackside in frag_irradiance
+- ShadowMap Perspective (no projection?)
+- (Implement Gaussian Blur)
+- LightDir nicht immer zu 0 0 0
+
+*/
+
+float samplePositions[] = {
+ 0.000000f, 0.000000f,
+ 1.633992f, 0.036795f,
+ 0.177801f, 1.717593f,
+ -0.194906f, 0.091094f,
+ -0.239737f, -0.220217f,
+ -0.003530f, -0.118219f,
+ 1.320107f, -0.181542f,
+ 5.970690f, 0.253378f,
+ -1.089250f, 4.958349f,
+ -4.015465f, 4.156699f,
+ -4.063099f, -4.110150f,
+ -0.638605f, -6.297663f,
+ 2.542348f, -3.245901f
+};
+
+float sampleWeights[] = {
+ 0.220441f, 0.487000f, 0.635000f,
+ 0.076356f, 0.064487f, 0.039097f,
+ 0.116515f, 0.103222f, 0.064912f,
+ 0.064844f, 0.086388f, 0.062272f,
+ 0.131798f, 0.151695f, 0.103676f,
+ 0.025690f, 0.042728f, 0.033003f,
+ 0.048593f, 0.064740f, 0.046131f,
+ 0.048092f, 0.003042f, 0.000400f,
+ 0.048845f, 0.005406f, 0.001222f,
+ 0.051322f, 0.006034f, 0.001420f,
+ 0.061428f, 0.009152f, 0.002511f,
+ 0.030936f, 0.002868f, 0.000652f,
+ 0.073580f, 0.023239f, 0.009703f
+};
+
+struct model {
+ std::vector<float> vertices;
+ std::vector<GLuint> indices;
+
+ void draw() {
+ if (VAO == 0) initVAO();
+ glBindVertexArray(VAO);
+ glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
+ glBindVertexArray(0);
+ }
+
+private:
+ void initVAO() {
+ GLuint VBO;
+ glGenBuffers(1, &VBO);
+
+ GLuint EBO;
+ glGenBuffers(1, &EBO);
+
+ glGenVertexArrays(1, &VAO);
+
+ glBindVertexArray(VAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(),
+ vertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(),
+ indices.data(), GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(0));
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
+
+ glBindVertexArray(0);
+ }
+ GLuint VAO = 0;
+};
+
+struct freecam {
+ glm::vec3 pos = glm::vec3(0, 0, -1);
+ glm::vec2 rot = glm::vec2(0, 0);
+
+ void update(sf::Window &window) {
+ int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;
+ int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;
+
+ rot.x += mouseDeltaX;
+ rot.y += mouseDeltaY;
+
+ forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));
+ forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));
+
+ glm::vec3 left = glm::rotate(glm::vec3(0, 0, 1), -rot.x / angleFactor + glm::radians(90.0f), glm::vec3(0, 1, 0));
+
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LShift))
+ moveFactor = 200;
+ else
+ moveFactor = 20;
+
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
+ pos += forward / moveFactor;
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
+ pos -= forward / moveFactor;
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
+ pos += left / moveFactor;
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
+ pos -= left / moveFactor;
+
+ limit();
+ }
+
+ void limit() {
+ rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);
+ rot.y = fmod(rot.y, glm::radians(360.0f) * angleFactor);
+ }
+
+ glm::mat4 getViewMatrix() {
+ forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));
+ forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));
+ glm::mat4 result = glm::lookAt(pos, pos + forward, up);
+ return result;
+ }
+
+private:
+ glm::vec3 forward = glm::vec3(0, 0, 1);
+ glm::vec3 up = glm::vec3(0, 1, 0);
+
+ const float angleFactor = 200;
+ float moveFactor = 20;
+};
+
+struct arccam {
+ glm::vec2 rot = glm::vec2(0, 0);
+ float radius = 1;
+
+ void update(sf::Window &window) {
+ int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;
+ int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;
+
+ rot.x += mouseDeltaX;
+ rot.y += mouseDeltaY;
+
+ limit(-89, 89);
+ }
+
+ void limit(float minY, float maxY) {
+ float angleX = rot.x / angleFactor;
+ float angleY = rot.y / angleFactor;
+
+ rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);
+
+ if (angleY > glm::radians(maxY))
+ rot.y = glm::radians(maxY) * angleFactor;
+ if (angleY < glm::radians(minY))
+ rot.y = glm::radians(minY) * angleFactor;
+ }
+
+ glm::vec3 getPos() {
+ float angle = rot.y / angleFactor;
+
+ float camY = sin(angle) * exp(radius);
+ float camZ = cos(angle) * exp(radius);
+
+ glm::vec3 result(0.0, camY, camZ);
+ return glm::rotate(result, -rot.x / angleFactor, glm::vec3(0, 1, 0));
+ }
+
+ glm::mat4 getViewMatrix() {
+ float angle = rot.y / angleFactor;
+
+ float camY = sin(angle) * exp(radius);
+ float camZ = cos(angle) * exp(radius);
+ glm::mat4 result = glm::lookAt(glm::vec3(0.0, camY, camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
+ result = glm::rotate(result, rot.x / angleFactor, glm::vec3(0, 1, 0));
+
+ return result;
+ }
+
+private:
+ const float angleFactor = 200;
+};
+
+std::string readFile(std::string filename) {
+ std::ifstream ifs(filename, std::ios::binary);
+ std::string result, line;
+ while (std::getline(ifs, line))
+ result += line + "\n";
+
+ return result;
+}
+
+model loadModel(const std::string &filename) {
+ Assimp::Importer importer;
+
+ const aiScene *scene = importer.ReadFile(
+ filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |
+ aiProcess_SortByPType | aiProcess_GenSmoothNormals |
+ aiProcess_GenUVCoords);
+
+ model result;
+
+ printf("uv channels: %d\n", scene->mMeshes[0]->GetNumUVChannels());
+
+ for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {
+ aiVector3D v = scene->mMeshes[0]->mVertices[i];
+ aiVector3D n = scene->mMeshes[0]->mNormals[i];
+ result.vertices.push_back(v.x * 100);
+ result.vertices.push_back(v.y * 100);
+ result.vertices.push_back(v.z * 100);
+ result.vertices.push_back(n.x * 100);
+ result.vertices.push_back(n.y * 100);
+ result.vertices.push_back(n.z * 100);
+ }
+
+ for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {
+ aiFace f = scene->mMeshes[0]->mFaces[i];
+ for (int j = 0; j < f.mNumIndices; j++) {
+ result.indices.push_back(f.mIndices[j]);
+ }
+ }
+
+ return result;
+}
+
+GLuint compileShaders(const char *vertFilename, const char *fragFilename) {
+ GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
+ std::string vertSource = readFile(vertFilename);
+ const char *vertAddr = vertSource.c_str();
+ glShaderSource(vertShader, 1, &vertAddr, NULL);
+ glCompileShader(vertShader);
+
+ int success;
+ char infoLog[512];
+ glGetShaderiv(vertShader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(vertShader, 512, NULL, infoLog);
+ printf("Error compiling vertex shader(%s): %s\n", vertFilename, infoLog);
+ }
+
+ GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
+ std::string fragSource = readFile(fragFilename);
+ const char *fragAddr = fragSource.c_str();
+ glShaderSource(fragShader, 1, &fragAddr, NULL);
+ glCompileShader(fragShader);
+
+ glGetShaderiv(fragShader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(fragShader, 512, NULL, infoLog);
+ printf("Error compiling fragment shader(%s): %s\n", fragFilename, infoLog);
+ }
+
+ // Link Shader Program
+
+ GLuint shaderProgram = glCreateProgram();
+ glAttachShader(shaderProgram, vertShader);
+ glAttachShader(shaderProgram, fragShader);
+ glLinkProgram(shaderProgram);
+
+ glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
+ printf("Error linking shader program: %s\n", infoLog);
+ }
+
+ glDeleteShader(vertShader);
+ glDeleteShader(fragShader);
+
+ return shaderProgram;
+}
+
+struct framebuffer {
+ framebuffer(const char *vertFilename, const char *fragFilename, int width, int height) {
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glGenTextures(1, &renderTexture);
+ glBindTexture(GL_TEXTURE_2D, renderTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ //glBindTexture(GL_TEXTURE_2D, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);
+
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+ //glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
+ printf("Successfully created framebuffer\n");
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ screenShaderProgram = compileShaders(vertFilename, fragFilename);
+ glUseProgram(screenShaderProgram);
+ glUniform1i(glGetUniformLocation(screenShaderProgram, "screenTexture"), 0);
+
+ // Screen VAO
+
+ glGenBuffers(1, &screenVBO);
+
+ glGenVertexArrays(1, &screenVAO);
+
+ glBindVertexArray(screenVAO);
+
+ float screenVerts[] = {
+ -1.0f, +1.0f, +0.0f, +1.0f,
+ -1.0f, -1.0f, +0.0f, +0.0f,
+ +1.0f, -1.0f, +1.0f, +0.0f,
+
+ -1.0f, +1.0f, +0.0f, +1.0f,
+ +1.0f, -1.0f, +1.0f, +0.0f,
+ +1.0f, +1.0f, +1.0f, +1.0f,
+ };
+
+ glBindBuffer(GL_ARRAY_BUFFER, screenVBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4,
+ screenVerts, GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(0));
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2));
+
+ glBindVertexArray(0);
+ }
+ ~framebuffer() {
+ glDeleteFramebuffers(1, &fbo);
+ }
+
+ GLuint fbo;
+ GLuint renderTexture;
+ GLuint rbo;
+ GLuint screenShaderProgram;
+ GLuint screenVBO;
+ GLuint screenVAO;
+};
+
+int main() {
+ // Window Setup
+
+ const int width = 1600, height = 900;
+
+ sf::ContextSettings settings;
+ settings.depthBits = 24;
+ settings.antialiasingLevel = 0;
+ settings.majorVersion = 4;
+ settings.minorVersion = 6;
+
+ sf::RenderWindow window(sf::VideoMode(1600, 900), "Subsurface Scattering",
+ sf::Style::Default, settings);
+ window.setVerticalSyncEnabled(true);
+
+ ImGui::SFML::Init(window);
+
+ // Initialize GLEW
+
+ if (glewInit() != GLEW_OK) {
+ }
+
+ GLuint shaderProgramShadowmap = compileShaders("shaders/vert_shadowmap.glsl", "shaders/frag_shadowmap.glsl");
+ GLuint shaderProgramIrradiance = compileShaders("shaders/vert_irradiance.glsl", "shaders/frag_irradiance.glsl");
+
+ //model m = loadModel("models/Isotrop-upperjaw.ply");
+ model m = loadModel("models/african_head/african_head.obj");
+
+ arccam arcCam;
+ freecam freeCam;
+
+ // MVP
+
+ glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));
+
+ glm::mat4 view, lightView;
+
+ glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);
+ glm::mat4 lightProj = glm::perspective(glm::radians(90.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);
+
+ // Framebuffer
+ framebuffer fb_shadowmap("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);
+ framebuffer fb_irradiance("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);
+
+ // Config
+
+ const struct {
+ bool wireframe = false;
+ bool freecam = false;
+ int renderState = 2;
+ float color[3] = { 0.7f, 0.4f, 0.4f };
+ glm::vec3 lightPos = glm::vec3(0.0f, 0.04f, -0.08f);
+ float transmittanceScale = 0.005f;
+ float powBase = 2.718;
+ float powFactor = 1;
+ } DefaultOptions;
+
+ auto options = DefaultOptions;
+
+ sf::Clock deltaClock;
+
+ bool prevMouse = false;
+
+ bool running = true;
+ while (running) {
+ // Events
+
+ sf::Event event;
+ while (window.pollEvent(event)) {
+ ImGui::SFML::ProcessEvent(event);
+
+ if (event.type == sf::Event::EventType::Closed) {
+ running = false;
+ } else if (event.type == sf::Event::EventType::Resized) {
+ glViewport(0, 0, event.size.width, event.size.height);
+ } else if (event.type == sf::Event::EventType::KeyReleased) {
+ using keys = sf::Keyboard;
+ switch (event.key.code) {
+ case keys::Escape:
+ running = false;
+ break;
+ }
+ } else if (event.type == sf::Event::EventType::MouseWheelScrolled) {
+ if (! options.freecam) {
+ arcCam.radius -= event.mouseWheelScroll.delta / 5.0f;
+ }
+ }
+ }
+
+ // Update
+
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
+ window.setMouseCursorVisible(false);
+
+ if (prevMouse) {
+ if (options.freecam)
+ freeCam.update(window);
+ else
+ arcCam.update(window);
+ }
+
+
+ sf::Mouse::setPosition(sf::Vector2i(
+ window.getSize().x / 2,
+ window.getSize().y / 2
+ ), window);
+ } else {
+ window.setMouseCursorVisible(true);
+ }
+
+ prevMouse = sf::Mouse::isButtonPressed(sf::Mouse::Right);
+
+ // Render Shadowmap
+
+ glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
+ glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
+ glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fb_shadowmap.fbo);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+
+ if (options.wireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ else
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glUseProgram(shaderProgramShadowmap);
+
+ if (options.freecam)
+ view = freeCam.getViewMatrix();
+ else
+ view = arcCam.getViewMatrix();
+
+ lightView = glm::lookAt(options.lightPos, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
+
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramShadowmap, "model"),
+ 1, GL_FALSE, glm::value_ptr(model));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramShadowmap, "lightView"),
+ 1, GL_FALSE, glm::value_ptr(lightView));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramShadowmap, "projection"),
+ 1, GL_FALSE, glm::value_ptr(lightProj));
+
+ glUniform3fv(
+ glGetUniformLocation(shaderProgramShadowmap, "lightPos"),
+ 1, glm::value_ptr(options.lightPos));
+
+ m.draw();
+
+ // Render irradiance
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fb_irradiance.fbo);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+
+ if (options.wireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ else
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glUseProgram(shaderProgramIrradiance);
+
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "model"),
+ 1, GL_FALSE, glm::value_ptr(model));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "view"),
+ 1, GL_FALSE, glm::value_ptr(view));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightView"),
+ 1, GL_FALSE, glm::value_ptr(lightView));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightViewInv"),
+ 1, GL_FALSE, glm::value_ptr(glm::inverse(lightView)));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "projection"),
+ 1, GL_FALSE, glm::value_ptr(proj));
+ glUniformMatrix4fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightProjection"),
+ 1, GL_FALSE, glm::value_ptr(lightProj));
+ glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenWidth"), window.getSize().x);
+ glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenHeight"), window.getSize().y);
+ glUniform2fv(glGetUniformLocation(shaderProgramIrradiance, "samplePositions"), 13, samplePositions);
+ glUniform3fv(glGetUniformLocation(shaderProgramIrradiance, "sampleWeights"), 13, sampleWeights);
+
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "transmittanceScale"),
+ options.transmittanceScale);
+ glUniform1i(
+ glGetUniformLocation(shaderProgramIrradiance, "renderState"),
+ options.renderState);
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "powBase"),
+ options.powBase);
+ glUniform1f(
+ glGetUniformLocation(shaderProgramIrradiance, "powFactor"),
+ options.powFactor);
+
+ glUniform3fv(
+ glGetUniformLocation(shaderProgramIrradiance, "objectColor"),
+ 1, options.color);
+ glUniform3f(
+ glGetUniformLocation(shaderProgramIrradiance, "lightColor"),
+ 1.0f, 1.0f, 1.0f);
+ glUniform3fv(
+ glGetUniformLocation(shaderProgramIrradiance, "lightPos"),
+ 1, glm::value_ptr(options.lightPos));
+ glUniform3fv(
+ glGetUniformLocation(shaderProgramIrradiance, "viewPos"),
+ 1, glm::value_ptr(options.freecam ? freeCam.pos : arcCam.getPos()));
+
+ glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "shadowmapTexture"), 0);
+ glActiveTexture(GL_TEXTURE0 + 0);
+ glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);
+
+ m.draw();
+
+ // Render fbo to screen
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDisable(GL_DEPTH_TEST);
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(fb_irradiance.screenShaderProgram);
+
+ glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenWidth"), window.getSize().x);
+ glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenHeight"), window.getSize().y);
+ glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "renderState"), options.renderState);
+ glUniform2fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "samplePositions"), 13, samplePositions);
+ glUniform3fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "sampleWeights"), 13, sampleWeights);
+
+ glBindVertexArray(fb_irradiance.screenVAO);
+ glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "shadowmapTexture"), 0);
+ glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "irradianceTexture"), 1);
+ glActiveTexture(GL_TEXTURE0 + 0);
+ glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);
+ glActiveTexture(GL_TEXTURE0 + 1);
+ glBindTexture(GL_TEXTURE_2D, fb_irradiance.renderTexture);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glBindVertexArray(0);
+
+ ImGui::SFML::Update(window, deltaClock.restart());
+
+ ImGui::Begin("Options");
+ ImGui::Checkbox("Wireframe", &options.wireframe);
+ ImGui::Checkbox("Free Cam", &options.freecam);
+ ImGui::InputInt("Render State", &options.renderState);
+ ImGui::DragFloat3("Color", options.color, 0.01, 0, 1);
+ ImGui::DragFloat("Transmittance Scale", &options.transmittanceScale, 0.0001f, 0, 0.3);
+ ImGui::DragFloat("Pow Base", &options.powBase, 0.01f, 0, 4);
+ ImGui::DragFloat("Pow Factor", &options.powFactor, 0.01f, 0, 3);
+ ImGui::DragFloat3("Light Pos", glm::value_ptr(options.lightPos), 0.01, -5, 5);
+ if (options.freecam) {
+ ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);
+ ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);
+ if (ImGui::Button("Reset")) {
+ freeCam.pos = glm::vec3(0, 0, -1);
+ freeCam.rot = glm::vec2(0);
+ options = DefaultOptions;
+ }
+ } else {
+ ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);
+ ImGui::DragFloat("Radius", &arcCam.radius, 0.01f, -1.0f, 1.0f);
+ if (ImGui::Button("Reset")) {
+ arcCam.rot = glm::vec2(0);
+ arcCam.radius = 1;
+ options = DefaultOptions;
+ }
+ }
+ ImGui::End();
+
+ ImGui::SFML::Render(window);
+
+ window.display();
+ }
+
+ return 0;
+}
|
