From 49b705565518722c367e28effea80f6e4496e82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 5 Jan 2014 21:52:09 +0100 Subject: [PATCH] [WIP] Use simple normal map for opengl water --- src/basics/NoiseFunctionSimplex.cpp | 52 +++++++++++++++++++++++----- src/basics/NoiseFunctionSimplex.h | 3 +- src/render/opengl/OpenGLVariable.cpp | 2 +- src/render/opengl/OpenGLWater.cpp | 2 +- src/render/opengl/shaders/water.frag | 30 +++++++++++++++- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/basics/NoiseFunctionSimplex.cpp b/src/basics/NoiseFunctionSimplex.cpp index eac4da4..d680fe1 100644 --- a/src/basics/NoiseFunctionSimplex.cpp +++ b/src/basics/NoiseFunctionSimplex.cpp @@ -11,6 +11,8 @@ #include #include "Texture2D.h" #include "Color.h" +#include "Geometry.h" +#include "Vector3.h" typedef struct { @@ -479,24 +481,58 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w) } -static Texture2D *_sampleTexture = NULL; +static Texture2D *_valueTexture = NULL; -const Texture2D *NoiseFunctionSimplex::getSampleTexture() +const Texture2D *NoiseFunctionSimplex::getValueTexture() { - const int width = 1024; - const int height = 1024; - if (!_sampleTexture) + if (!_valueTexture) { - _sampleTexture = new Texture2D(width, height); + const int width = 1024; + const int height = 1024; + + _valueTexture = new Texture2D(width, height); + for (int x = 0; x < width; x++) { for (int z = 0; z < height; z++) { double val = noiseSimplexGet2DValue((double)x, (double)z); - _sampleTexture->setPixel(x, z, Color(val, val, val)); + _valueTexture->setPixel(x, z, Color(val, val, val)); } } } - return _sampleTexture; + return _valueTexture; +} + +static Texture2D *_normalTexture = NULL; + +const Texture2D *NoiseFunctionSimplex::getNormalTexture() +{ + if (!_normalTexture) + { + const int width = 1024; + const int height = 1024; + + _normalTexture = new Texture2D(width, height); + + for (int x = 0; x < width; x++) + { + for (int z = 0; z < height; z++) + { + double vcenter = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z); + double vsouth = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z + 0.001); + double veast = noiseSimplexGet2DValue(0.01 * (double)x + 0.001, 0.01 * (double)z); + + Vector3 normal = Geometry::getNormalFromTriangle(Vector3(0.0, vcenter, 0.0), + Vector3(0.0, vsouth, 0.01), + Vector3(0.01, veast, 0.0) + ); + + _normalTexture->setPixel(x, z, Color(normal.x, normal.y, normal.z)); + } + } + } + + return _normalTexture; } diff --git a/src/basics/NoiseFunctionSimplex.h b/src/basics/NoiseFunctionSimplex.h index 076b547..46c321f 100644 --- a/src/basics/NoiseFunctionSimplex.h +++ b/src/basics/NoiseFunctionSimplex.h @@ -9,7 +9,8 @@ namespace basics { class NoiseFunctionSimplex { public: - static const Texture2D *getSampleTexture(); + static const Texture2D *getValueTexture(); + static const Texture2D *getNormalTexture(); }; } diff --git a/src/render/opengl/OpenGLVariable.cpp b/src/render/opengl/OpenGLVariable.cpp index 1b7e422..55f9a3a 100644 --- a/src/render/opengl/OpenGLVariable.cpp +++ b/src/render/opengl/OpenGLVariable.cpp @@ -134,7 +134,7 @@ void OpenGLVariable::set(const Color &color) assert(type == TYPE_NONE or type == TYPE_COLOR); type = TYPE_COLOR; - value_color = QColor(color.r, color.g, color.b); + value_color = QColor::fromRgbF(color.r, color.g, color.b); } void OpenGLVariable::uploadTexture(OpenGLRenderer* renderer) diff --git a/src/render/opengl/OpenGLWater.cpp b/src/render/opengl/OpenGLWater.cpp index 9a316fe..483833d 100644 --- a/src/render/opengl/OpenGLWater.cpp +++ b/src/render/opengl/OpenGLWater.cpp @@ -43,7 +43,7 @@ void OpenGLWater::update() Color water_color = renderer->getScenery()->getWater()->material->_rgb; renderer->getSharedState()->set("waterColor", water_color); - renderer->getSharedState()->set("simplexSampler", NoiseFunctionSimplex::getSampleTexture(), true, false); + renderer->getSharedState()->set("simplexSampler", NoiseFunctionSimplex::getNormalTexture(), true, true); } void OpenGLWater::render() diff --git a/src/render/opengl/shaders/water.frag b/src/render/opengl/shaders/water.frag index 591eadd..83bc808 100644 --- a/src/render/opengl/shaders/water.frag +++ b/src/render/opengl/shaders/water.frag @@ -1,10 +1,38 @@ uniform vec4 waterColor; uniform sampler2D simplexSampler; +vec4 applyLighting(vec3 location, vec3 normal, vec4 color, float shininess) +{ + // TEMP phong lighting implementation for testing + vec3 N = normalize(normal); + vec3 L = sunDirection; + vec3 E = normalize(cameraLocation - location); + vec3 R = normalize(-reflect(L, N)); + + //calculate Ambient Term: + vec4 Iamb = vec4(0.1, 0.1, 0.1, 1.0); + + //calculate Diffuse Term: + vec4 Idiff = vec4(3.0, 3.0, 3.0, 1.0) * color * max(dot(N, L), 0.0); + + // calculate Specular Term: + vec4 Ispec = vec4(3.0, 3.0, 3.0, 1.0) * pow(max(dot(R,E),0.0),0.3*shininess); + + // write Total Color: + return Iamb + Idiff + Ispec; +} + void main(void) { //gl_FragColor = waterColor; - gl_FragColor = texture2D(simplexSampler, unprojected.xz * 0.01); + //gl_FragColor = texture2D(simplexSampler, unprojected.xz * 0.01); + vec3 normal = vec3(0.0, 0.0, 0.0); + for (float scaling = 1.0; scaling < 50.0; scaling *= 1.5) + { + normal += texture2D(simplexSampler, unprojected.xz * 0.01 * scaling).xyz; + } + + gl_FragColor = applyLighting(unprojected, normalize(normal), waterColor, 100.0); gl_FragColor = applyAerialPerspective(gl_FragColor);