diff options
author | Jesse Barker <jesse.barker@linaro.org> | 2012-10-22 14:30:36 -0700 |
---|---|---|
committer | Jesse Barker <jesse.barker@linaro.org> | 2012-10-22 14:30:36 -0700 |
commit | f039dbaa723236bfdd7022543bb8e4e5e9a10811 (patch) | |
tree | b73e2e8a97d851dca63afbb82422c7a023c01d8a | |
parent | c46d126bc97e839f135419d6ea4aaade3732ab97 (diff) | |
download | glmark2-f039dbaa723236bfdd7022543bb8e4e5e9a10811.tar.gz |
SceneShadow: Finally add in the ground with the shadow cast upon it.
-rw-r--r-- | data/shaders/shadow.frag | 17 | ||||
-rw-r--r-- | data/shaders/shadow.vert | 16 | ||||
-rw-r--r-- | src/scene-shadow.cpp | 134 |
3 files changed, 164 insertions, 3 deletions
diff --git a/data/shaders/shadow.frag b/data/shaders/shadow.frag new file mode 100644 index 0000000..6b86ace --- /dev/null +++ b/data/shaders/shadow.frag @@ -0,0 +1,17 @@ +uniform sampler2D ShadowMap; + +varying vec4 Color; +varying vec4 ShadowCoord; + +void main() +{ + vec4 sc_perspective = ShadowCoord / ShadowCoord.w; + sc_perspective.z += 0.1505; + vec4 shadow_value = texture2D(ShadowMap, sc_perspective.st); + float light_distance = shadow_value.z; + float shadow = 1.0; + if (ShadowCoord.w > 0.0 && light_distance < sc_perspective.z) { + shadow = 0.5; + } + gl_FragColor = vec4(shadow * Color.rgb, 1.0); +} diff --git a/data/shaders/shadow.vert b/data/shaders/shadow.vert new file mode 100644 index 0000000..a8ba2b4 --- /dev/null +++ b/data/shaders/shadow.vert @@ -0,0 +1,16 @@ +attribute vec2 position; + +uniform mat4 LightMatrix; +uniform mat4 ModelViewProjectionMatrix; + +varying vec4 ShadowCoord; +varying vec4 Color; + +void main() +{ + Color = MaterialDiffuse; + + vec4 pos4 = vec4(position, 0.0, 1.0); + ShadowCoord = LightMatrix * pos4; + gl_Position = ModelViewProjectionMatrix * pos4; +} diff --git a/src/scene-shadow.cpp b/src/scene-shadow.cpp index cf2423c..77f3bc0 100644 --- a/src/scene-shadow.cpp +++ b/src/scene-shadow.cpp @@ -33,6 +33,7 @@ using LibMatrix::Stack4; using LibMatrix::mat4; using LibMatrix::vec4; using LibMatrix::vec3; +using LibMatrix::vec2; static const vec4 lightPosition(0.0f, 3.0f, 2.0f, 1.0f); @@ -65,7 +66,7 @@ public: void teardown(); void enable(const mat4& mvp); void disable(); - unsigned int depthTexture() { return tex_; } + unsigned int texture() { return tex_; } Program& program() { return program_; } }; @@ -146,10 +147,130 @@ void DepthRenderTarget::disable() glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } +// +// The actual shadow pass is really just a quad projected into the scene +// with the horse's shadow cast upon it. In the vertex stage, we compute +// a texture coordinate for the depth texture look-up by transforming the +// current vertex position using a matrix describing the light's view point. +// In the fragment stage, that coordinate is perspective corrected, and +// used to sample the depth texture. If the depth value for that fragment +// (effectively the distance from the light to the object at that point) +// is less than the Z component of that coordinate (effectively the distance +// from the light to the ground at that point) then that location is in shadow. +// +class GroundRenderer +{ + Program program_; + Stack4 light_; + Stack4 modelview_; + mat4 projection_; + int positionLocation_; + unsigned int bufferObject_; + unsigned int texture_; + vector<vec2> vertices_; + vector<vec2> texcoords_; + +public: + GroundRenderer() : + positionLocation_(0), + bufferObject_(0) {} + ~GroundRenderer() {} + bool setup(const mat4& projection, unsigned int texture); + void teardown(); + void draw(); +}; + +bool +GroundRenderer::setup(const mat4& projection, unsigned int texture) +{ + projection_ = projection; + texture_ = texture; + + // Program set up + static const vec4 materialDiffuse(0.3f, 0.3f, 0.3f, 1.0f); + static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/shadow.vert"); + static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/shadow.frag"); + ShaderSource vtx_source(vtx_shader_filename); + ShaderSource frg_source(frg_shader_filename); + + vtx_source.add_const("MaterialDiffuse", materialDiffuse); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { + return false; + } + positionLocation_ = program_["position"].location(); + + // Set up the position data for our "quad". + vertices_.push_back(vec2(-1.0, -1.0)); + vertices_.push_back(vec2(1.0, -1.0)); + vertices_.push_back(vec2(-1.0, 1.0)); + vertices_.push_back(vec2(1.0, 1.0)); + + // Set up the VBO and stash our position data in it. + glGenBuffers(1, &bufferObject_); + glBindBuffer(GL_ARRAY_BUFFER, bufferObject_); + glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(vec2), + &vertices_.front(), GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // Initialize the light stack with a bias matrix that will convert + // values in the range of [-1, 1] to [0, 1)]. + light_.translate(0.5, 0.5, 0.5); + light_.scale(0.5, 0.5, 0.5); + light_ *= projection_; + light_.lookAt(lightPosition.x(), lightPosition.y(), lightPosition.z(), + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + return true; +} + +void +GroundRenderer::teardown() +{ + program_.stop(); + program_.release(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &bufferObject_); + bufferObject_ = 0; + texture_= 0; + vertices_.clear(); +} + +void +GroundRenderer::draw() +{ + // Need to add uniforms for the shadow texture, and transformation to + // "lay the quad down". + modelview_.push(); + modelview_.translate(projection_[0][3], projection_[1][3] - 0.8, projection_[2][3] - 0.5); + modelview_.rotate(-85.0, 1.0, 0.0, 0.0); + modelview_.scale(2.0, 2.0, 2.0); + mat4 mvp(projection_); + mvp *= modelview_.getCurrent(); + + glBindBuffer(GL_ARRAY_BUFFER, bufferObject_); + program_.start(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_); + program_["ShadowMap"] = 0; + program_["LightMatrix"] = light_.getCurrent(); + program_["ModelViewProjectionMatrix"] = mvp; + + glEnableVertexAttribArray(positionLocation_); + glVertexAttribPointer(positionLocation_, 2, GL_FLOAT, GL_FALSE, 0, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableVertexAttribArray(positionLocation_); + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + modelview_.pop(); +} + class ShadowPrivate { Canvas& canvas_; DepthRenderTarget depthTarget_; + GroundRenderer ground_; Program program_; Stack4 modelview_; Stack4 projection_; @@ -234,13 +355,18 @@ ShadowPrivate::setup(map<string, Scene::Option>& options) fovy /= M_PI; fovy *= 180.0; float aspect(static_cast<float>(canvas_.width())/static_cast<float>(canvas_.height())); - projection_.perspective(fovy, aspect, 2.0, 2.0 + diameter); + projection_.perspective(fovy, aspect, 2.0, 50.0); if (!depthTarget_.setup(canvas_.width(), canvas_.height())) { Log::error("Failed to set up the render target for the depth pass\n"); return false; } + if (!ground_.setup(projection_.getCurrent(), depthTarget_.texture())) { + Log::error("Failed to set up the ground renderer\n"); + return false; + } + return true; } @@ -249,6 +375,7 @@ void ShadowPrivate::teardown() { depthTarget_.teardown(); + ground_.teardown(); program_.stop(); program_.release(); mesh_.reset(); @@ -290,7 +417,8 @@ ShadowPrivate::draw() } depthTarget_.disable(); - // TODO: Ground rendering using the above generated texture... + // Ground rendering using the above generated texture... + ground_.draw(); // Draw the "normal" view of the horse modelview_.push(); |