diff --git a/shaders/shader_parallax.frag b/shaders/shader_parallax.frag new file mode 100644 index 0000000..6744133 --- /dev/null +++ b/shaders/shader_parallax.frag @@ -0,0 +1,85 @@ +#version 330 core +out vec4 FragColor; + +in VS_OUT { + vec3 FragPos; + vec2 TexCoords; + vec3 TangentLightPos; + vec3 TangentViewPos; + vec3 TangentFragPos; +} fs_in; + +uniform sampler2D diffuseTexture; +uniform sampler2D normalTexture; +uniform sampler2D depthTexture; + +uniform float heightScale; + +vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir) +{ + // number of depth layers + const float minLayers = 8; + const float maxLayers = 32; + float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir))); + // calculate the size of each layer + float layerDepth = 1.0 / numLayers; + // depth of current layer + float currentLayerDepth = 0.0; + // the amount to shift the texture coordinates per layer (from vector P) + vec2 P = viewDir.xy / viewDir.z * heightScale; + vec2 deltaTexCoords = P / numLayers; + + // get initial values + vec2 currentTexCoords = texCoords; + float currentdepthTextureValue = texture(depthTexture, currentTexCoords).r; + + while(currentLayerDepth < currentdepthTextureValue) + { + // shift texture coordinates along direction of P + currentTexCoords -= deltaTexCoords; + // get depthTexture value at current texture coordinates + currentdepthTextureValue = texture(depthTexture, currentTexCoords).r; + // get depth of next layer + currentLayerDepth += layerDepth; + } + + // get texture coordinates before collision (reverse operations) + vec2 prevTexCoords = currentTexCoords + deltaTexCoords; + + // get depth after and before collision for linear interpolation + float afterDepth = currentdepthTextureValue - currentLayerDepth; + float beforeDepth = texture(depthTexture, prevTexCoords).r - currentLayerDepth + layerDepth; + + // interpolation of texture coordinates + float weight = afterDepth / (afterDepth - beforeDepth); + vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); + + return finalTexCoords; +} + +void main() +{ + vec3 fragColor = vec3(0,0,0); + vec3 viewDir = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos); + vec2 texCoords = ParallaxMapping(fs_in.TexCoords, viewDir); + if(texCoords.x > 1.0 || texCoords.y > 1.0 || texCoords.x < 0.0 || texCoords.y < 0.0) + discard; + + vec3 texture = texture2D(diffuseTexture, texCoords).rgb; + vec3 ambient = vec3(0.1, 0.1, 0.1) * texture; + + // obtain normal from normal map + vec3 normal = texture2D(normalTexture, texCoords).rgb; + normal = normalize(normal * 2.0 - 1.0); + + vec3 lightDir = normalize(fs_in.TangentLightPos[0] - fs_in.TangentFragPos); + float diff = max(0,dot(normal,normalize(lightDir))); + vec3 diffuse = diff * texture; + // specular + vec3 reflectDir = reflect(-lightDir, normal); + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0); + + vec3 specular = vec3(0.2) * spec; + FragColor = vec4(ambient + diffuse + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/shader_parallax.vert b/shaders/shader_parallax.vert new file mode 100644 index 0000000..9401256 --- /dev/null +++ b/shaders/shader_parallax.vert @@ -0,0 +1,44 @@ +#version 330 core +layout(location = 0) in vec3 vertexPosition; +layout(location = 1) in vec2 vertexTexCoord; +layout(location = 2) in vec3 vertexNormal; +layout (location = 3) in vec3 aTangent; +layout (location = 4) in vec3 aBitangent; + +out VS_OUT { + vec3 FragPos; + vec2 TexCoords; + vec3 TangentLightPos; + vec3 TangentViewPos; + vec3 TangentFragPos; +} vs_out; + +uniform mat4 projection; +uniform mat4 view; +uniform mat4 modelMatrix; +uniform mat4 transformation; + + +uniform vec3 lightPos; +uniform vec3 viewPos; + +void main() +{ + gl_Position = transformation * vec4(vertexPosition, 1.0); + mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); + + gl_Position = projection * view * modelMatrix * vec4(vertexPosition, 1.0); + vs_out.FragPos = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + vs_out.TexCoords = vertexTexCoord; + + vec3 T = normalize(normalMatrix * aTangent); + vec3 N = normalize(normalMatrix * vertexNormal); + T = normalize(T - dot(T, N) * N); + vec3 B = cross(N, T); + + mat3 TBN = mat3(T, B, N); + + vs_out.TangentLightPos = TBN * lightPos; + vs_out.TangentViewPos = TBN * viewPos; + vs_out.TangentFragPos = (modelMatrix*vec4(vertexPosition,1)).xyz; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5967cda..a393a5d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,7 @@ GLuint programBloom; GLuint programNormal; GLuint programParticle; GLuint programAsteroid; +GLuint programParallax; //bloompart unsigned int pingpongFBO[2]; @@ -56,6 +57,8 @@ bool bothEngines = true; //textures GLuint sunTexture; GLuint earthTexture; +GLuint earthNormalTexture; +GLuint earthSpecularTexture; GLuint marsTexture; GLuint moonTexture; GLuint skyboxTexture; @@ -133,6 +136,10 @@ struct Object glm::mat4 invModelM; std::shared_ptr modelParent; GLuint textureID; + //part for parallax mapping + GLuint textureNormal = -1; + GLuint textureSpecular = -1; + //end of part GLuint shaderID; glm::vec3 color; }; @@ -220,6 +227,8 @@ void renderQuad() 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, }; + glm::vec3 nm(0.0f, 0.0f, 1.0f); + glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); glBindVertexArray(quadVAO); @@ -328,16 +337,28 @@ void drawFromAssimpTexture(GLuint program, std::shared_ptr model, glm::ma void drawObject(Object & obj) { glUseProgram(obj.shaderID); - glm::mat4 transformation = perspectiveMatrix * cameraMatrix * obj.modelM; - - glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "modelMatrix"), 1, GL_FALSE, (float*)&obj.modelM); glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "transformation"), 1, GL_FALSE, (float*)&transformation); - - glUniform3f(glGetUniformLocation(obj.shaderID, "objectColor"), obj.color.r, obj.color.g, obj.color.b); - if (obj.textureID != -1) - Core::SetActiveTexture(obj.textureID, "diffuseTexture", obj.shaderID, 0); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "modelMatrix"), 1, GL_FALSE, (float*)&obj.modelM); + if (obj.shaderID == programParallax) + { + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "projection"), 1, GL_FALSE, (float*)&perspectiveMatrix); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "view"), 1, GL_FALSE, (float*)&cameraMatrix); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "viewPos"), 1, GL_FALSE, (float*)&cameraPos); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "lightPos"), 1, GL_FALSE, (float*)&lights); + glUniformMatrix4fv(glGetUniformLocation(obj.shaderID, "heightScale"), 1, GL_FALSE, (float*)&cameraPos[1]); + Core::SetActiveTexture(obj.textureID, "diffuseTexture", obj.shaderID, 1); + Core::SetActiveTexture(obj.textureNormal, "normalTexture", obj.shaderID, 0); + Core::SetActiveTexture(obj.textureSpecular, "depthTexture", obj.shaderID, 2); + } + else + { + glUniform3f(glGetUniformLocation(obj.shaderID, "objectColor"), obj.color.r, obj.color.g, obj.color.b); + if (obj.textureID != -1) + Core::SetActiveTexture(obj.textureID, "diffuseTexture", obj.shaderID, 0); + } obj.modelParent->Draw(obj.shaderID); glUseProgram(0); } @@ -391,6 +412,7 @@ unsigned int loadCubemap(std::vector faces) return textureID; } + void drawSkybox(GLuint program, std::shared_ptr cubeModel, GLuint texID) { glUseProgram(program); @@ -895,7 +917,9 @@ void initObjects() planet.invModelM = glm::inverse(earthModelMatrix); planet.modelParent = sphere; planet.textureID = earthTexture; - planet.shaderID = programTex; + planet.textureNormal = earthNormalTexture; + planet.textureSpecular = earthSpecularTexture; + planet.shaderID = programParallax; planet.color = glm::vec3(1.0f); objects.push_back(planet); @@ -955,6 +979,7 @@ void init() programBloom = shaderLoader.CreateProgram("shaders/shader_bloom.vert", "shaders/shader_bloom.frag"); programParticle = shaderLoader.CreateProgram("shaders/shader_particle.vert", "shaders/shader_particle.frag"); programAsteroid = shaderLoader.CreateProgram("shaders/shader_asteroid.vert", "shaders/shader_asteroid.frag"); + programParallax = shaderLoader.CreateProgram("shaders/shader_parallax.vert", "shaders/shader_parallax.frag"); glUseProgram(programBlur); glUniform1i(glGetUniformLocation(programBlur, "image"), 0); @@ -962,7 +987,12 @@ void init() glUniform1i(glGetUniformLocation(programBloom, "scene"), 0); glUniform1i(glGetUniformLocation(programBloom, "bloomBlur"), 1); glUniform2f(glGetUniformLocation(programBloom, "screenSize"), 1.0f / SCR_WIDTH, 1.0f / SCR_HEIGHT); + glUseProgram(programParallax); + glUniform1i(glGetUniformLocation(programParallax, "diffuseMap"), 0); + glUniform1i(glGetUniformLocation(programParallax, "normalMap"), 1); + glUniform1i(glGetUniformLocation(programParallax, "depthMap"), 2); glUseProgram(0); + corvette = std::make_shared("models/Corvette-F3.obj"); @@ -973,6 +1003,8 @@ void init() sunTexture = Core::LoadTexture("textures/sun.png"); earthTexture = Core::LoadTexture("textures/earth2.png"); + earthNormalTexture = Core::LoadTexture("textures/earth2_normal.png"); + earthSpecularTexture = Core::LoadTexture("textures/earth2_specular.png"); moonTexture = Core::LoadTexture("textures/moon.png"); particleTexture = Core::LoadTexture("textures/sun.png"); marsTexture = Core::LoadTexture("models/textures/Mars/2k_mars.png"); @@ -1022,6 +1054,7 @@ void onReshape(int width, int height) frustumScale = (float)width / (float)height; glViewport(0, 0, width, height); } + void idle() { glutPostRedisplay(); diff --git a/textures/earth2_normal.png b/textures/earth2_normal.png new file mode 100644 index 0000000..44370f1 Binary files /dev/null and b/textures/earth2_normal.png differ diff --git a/textures/earth2_specular.png b/textures/earth2_specular.png new file mode 100644 index 0000000..2730964 Binary files /dev/null and b/textures/earth2_specular.png differ