From b00c4a2ee5648d25402684302122dabfffa318bf Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Fri, 7 Dec 2012 11:57:44 -0800 Subject: SceneRefract: First cut at a new scene that will demonstrate the refraction of light through a transparent object. --- data/shaders/light-refract.frag | 24 +++ data/shaders/light-refract.vert | 23 +++ src/android.cpp | 1 + src/default-benchmarks.h | 1 + src/main.cpp | 1 + src/scene-refract.cpp | 436 ++++++++++++++++++++++++++++++++++++++++ src/scene-refract.h | 97 +++++++++ src/scene.h | 17 ++ 8 files changed, 600 insertions(+) create mode 100644 data/shaders/light-refract.frag create mode 100644 data/shaders/light-refract.vert create mode 100644 src/scene-refract.cpp create mode 100644 src/scene-refract.h diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag new file mode 100644 index 0000000..f7ae395 --- /dev/null +++ b/data/shaders/light-refract.frag @@ -0,0 +1,24 @@ +uniform sampler2D DistanceMap; + +varying vec3 vertex_normal; +varying vec4 vertex_position; + +void main() +{ + const vec4 lightAmbient = vec4(0.1, 0.1, 0.1, 1.0); + const vec4 lightSpecular = vec4(0.8, 0.8, 0.8, 1.0); + const vec4 matAmbient = vec4(0.2, 0.2, 0.2, 1.0); + const vec4 matSpecular = vec4(1.0, 1.0, 1.0, 1.0); + const float matShininess = 100.0; + vec3 eye_direction = normalize(-vertex_position.xyz); + vec3 light_direction = normalize(LightSourcePosition.xyz/LightSourcePosition.w - + vertex_position.xyz/vertex_position.w); + vec3 normalized_normal = normalize(vertex_normal); + vec3 reflection = reflect(-light_direction, normalized_normal); + float specularTerm = pow(max(0.0, dot(reflection, eye_direction)), matShininess); + float diffuseTerm = max(0.0, dot(normalized_normal, light_direction)); + vec4 specular = (lightSpecular * matSpecular); + vec4 ambient = (lightAmbient * matAmbient); + vec4 diffuse = (LightColor * MaterialDiffuse); + gl_FragColor = (specular * specularTerm) + ambient + (diffuse * diffuseTerm); +} diff --git a/data/shaders/light-refract.vert b/data/shaders/light-refract.vert new file mode 100644 index 0000000..8a95ca7 --- /dev/null +++ b/data/shaders/light-refract.vert @@ -0,0 +1,23 @@ +attribute vec3 position; +attribute vec3 normal; + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 NormalMatrix; +uniform mat4 ModelViewMatrix; + +varying vec3 vertex_normal; +varying vec4 vertex_position; + +void main(void) +{ + vec4 current_position = vec4(position, 1.0); + + // Transform the normal to eye coordinates + vertex_normal = normalize(vec3(NormalMatrix * vec4(normal, 1.0))); + + // Transform the current position to eye coordinates + vertex_position = ModelViewMatrix * current_position; + + // Transform the current position to clip coordinates + gl_Position = ModelViewProjectionMatrix * current_position; +} diff --git a/src/android.cpp b/src/android.cpp index 53a17f7..d098626 100644 --- a/src/android.cpp +++ b/src/android.cpp @@ -276,6 +276,7 @@ create_and_add_scenes(std::vector& scenes, Canvas& canvas) scenes.push_back(new SceneTerrain(canvas)); scenes.push_back(new SceneJellyfish(canvas)); scenes.push_back(new SceneShadow(canvas)); + scenes.push_back(new SceneRefract(canvas)); } diff --git a/src/default-benchmarks.h b/src/default-benchmarks.h index 45f7672..3726a61 100644 --- a/src/default-benchmarks.h +++ b/src/default-benchmarks.h @@ -64,6 +64,7 @@ private: benchmarks.push_back("jellyfish"); benchmarks.push_back("terrain"); benchmarks.push_back("shadow"); + benchmarks.push_back("refract"); benchmarks.push_back("conditionals:vertex-steps=0:fragment-steps=0"); benchmarks.push_back("conditionals:vertex-steps=0:fragment-steps=5"); benchmarks.push_back("conditionals:vertex-steps=5:fragment-steps=0"); diff --git a/src/main.cpp b/src/main.cpp index d310a51..40a23d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,6 +64,7 @@ add_and_register_scenes(vector& scenes, Canvas& canvas) scenes.push_back(new SceneTerrain(canvas)); scenes.push_back(new SceneJellyfish(canvas)); scenes.push_back(new SceneShadow(canvas)); + scenes.push_back(new SceneRefract(canvas)); for (vector::const_iterator iter = scenes.begin(); iter != scenes.end(); diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp new file mode 100644 index 0000000..b1d8dcc --- /dev/null +++ b/src/scene-refract.cpp @@ -0,0 +1,436 @@ +// +// Copyright © 2012 Linaro Limited +// +// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. +// +// glmark2 is free software: you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// glmark2. If not, see . +// +// Authors: +// Jesse Barker +// +#include "scene-refract.h" +#include "model.h" +#include "texture.h" +#include "util.h" +#include "log.h" +#include "shader-source.h" + +using std::string; +using std::vector; +using std::map; +using LibMatrix::mat4; +using LibMatrix::vec4; +using LibMatrix::vec3; + +static const vec4 lightPosition(0.0f, 3.0f, 2.0f, 1.0f); + +// +// Public interfaces +// + +SceneRefract::SceneRefract(Canvas& canvas) : + Scene(canvas, "refract"), + priv_(0) +{ + const ModelMap& modelMap = Model::find_models(); + string optionValues; + for (ModelMap::const_iterator modelIt = modelMap.begin(); + modelIt != modelMap.end(); + modelIt++) + { + static bool doSeparator(false); + if (doSeparator) + { + optionValues += ","; + } + const string& curName = modelIt->first; + optionValues += curName; + doSeparator = true; + } + options_["model"] = Scene::Option("model", "bunny", "Which model to use", + optionValues); + optionValues = ""; + const TextureMap& textureMap = Texture::find_textures(); + for (TextureMap::const_iterator textureIt = textureMap.begin(); + textureIt != textureMap.end(); + textureIt++) + { + static bool doSeparator(false); + if (doSeparator) + { + optionValues += ","; + } + const string& curName = textureIt->first; + optionValues += curName; + doSeparator = true; + } + options_["texture"] = Scene::Option("texture", "nasa1", "Which texture to use", + optionValues); + options_["use-vbo"] = Scene::Option("use-vbo", "true", + "Whether to use VBOs for rendering", + "false,true"); + options_["interleave"] = Scene::Option("interleave", "false", + "Whether to interleave vertex attribute data", + "false,true"); +} + +SceneRefract::~SceneRefract() +{ + delete priv_; +} + +bool +SceneRefract::supported(bool show_errors) +{ + static const string oes_depth_texture("GL_OES_depth_texture"); + static const string arb_depth_texture("GL_ARB_depth_texture"); + if (!GLExtensions::support(oes_depth_texture) && + !GLExtensions::support(arb_depth_texture)) { + if (show_errors) { + Log::error("We do not have the depth texture extension!!!\n"); + } + + return false; + } + return true; +} + +bool +SceneRefract::load() +{ + running_ = false; + return true; +} + +void +SceneRefract::unload() +{ +} + +bool +SceneRefract::setup() +{ + // If the scene isn't supported, don't bother to go through setup. + if (!supported(false) || !Scene::setup()) + { + return false; + } + + priv_ = new RefractPrivate(canvas_); + if (!priv_->setup(options_)) { + delete priv_; + priv_ = 0; + return false; + } + + // Set core scene timing after actual initialization so we don't measure + // set up time. + startTime_ = Util::get_timestamp_us() / 1000000.0; + lastUpdateTime_ = startTime_; + running_ = true; + + return true; +} + +void +SceneRefract::teardown() +{ + // Add scene-specific teardown here + priv_->teardown(); + Scene::teardown(); +} + +void +SceneRefract::update() +{ + Scene::update(); + // Add scene-specific update here + priv_->update(lastUpdateTime_ - startTime_); +} + +void +SceneRefract::draw() +{ + priv_->draw(); +} + +Scene::ValidationResult +SceneRefract::validate() +{ + return Scene::ValidationUnknown; +} + +// +// Private interfaces +// + +bool +DistanceRenderTarget::setup(unsigned int width, unsigned int height) +{ + canvas_width_ = width; + canvas_height_ = height; + width_ = canvas_width_ * 2; + height_ = canvas_height_ * 2; + + static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/depth.vert"); + static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/depth.frag"); + + ShaderSource vtx_source(vtx_shader_filename); + ShaderSource frg_source(frg_shader_filename); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { + return false; + } + + glGenTextures(1, &tex_); + glBindTexture(GL_TEXTURE_2D, tex_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width_, height_, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenFramebuffers(1, &fbo_); + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, + tex_, 0); + unsigned int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + Log::error("DepthRenderState::setup: glCheckFramebufferStatus failed (0x%x)\n", status); + return false; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return true; +} + +void +DistanceRenderTarget::teardown() +{ + program_.stop(); + program_.release(); + if (tex_) { + glDeleteTextures(1, &tex_); + tex_ = 0; + } + if (fbo_) { + glDeleteFramebuffers(1, &fbo_); + fbo_ = 0; + } +} + +void +DistanceRenderTarget::enable(const mat4& mvp) +{ + program_.start(); + program_["ModelViewProjectionMatrix"] = mvp; + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, + tex_, 0); + glViewport(0, 0, width_, height_); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glClear(GL_DEPTH_BUFFER_BIT); +} + +void DistanceRenderTarget::disable() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, canvas_width_, canvas_height_); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); +} + +bool +RefractPrivate::setup(map& options) +{ + // Program object setup + static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.vert"); + static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.frag"); + static const vec4 materialDiffuse(0.0f, 0.0f, 0.0f, 0.0f); + static const vec4 lightColor(1.0, 1.0, 1.0, 1.0); + + ShaderSource vtx_source(vtx_shader_filename); + ShaderSource frg_source(frg_shader_filename); + + frg_source.add_const("LightColor", lightColor); + frg_source.add_const("LightSourcePosition", lightPosition); + frg_source.add_const("MaterialDiffuse", materialDiffuse); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { + return false; + } + + const string& whichTexture(options["texture"].value); + if (!Texture::load(whichTexture, &texture_, GL_LINEAR, GL_LINEAR, 0)) + return false; + + // Model setup + Model model; + const string& whichModel(options["model"].value); + bool modelLoaded = model.load(whichModel); + + if(!modelLoaded) + return false; + + // Now that we're successfully loaded, there are a few quirks about + // some of the known models that we need to account for. The draw + // logic for the scene wants to rotate the model around the Y axis. + // Most of our models are described this way. Some need adjustment + // (an additional rotation that gets the model into the correct + // orientation). + // + // Here's a summary: + // + // Angel rotates around the Y axis + // Armadillo rotates around the Y axis + // Buddha rotates around the X axis + // Bunny rotates around the Y axis + // Dragon rotates around the X axis + // Horse rotates around the Y axis + if (whichModel == "buddha" || whichModel == "dragon") + { + orientModel_ = true; + orientationAngle_ = -90.0; + orientationVec_ = vec3(1.0, 0.0, 0.0); + } + else if (whichModel == "armadillo") + { + orientModel_ = true; + orientationAngle_ = 180.0; + orientationVec_ = vec3(0.0, 1.0, 0.0); + } + + model.calculate_normals(); + + // Mesh setup + vector > attribs; + attribs.push_back(std::pair(Model::AttribTypePosition, 3)); + attribs.push_back(std::pair(Model::AttribTypeNormal, 3)); + model.convert_to_mesh(mesh_, attribs); + + useVbo_ = (options["use-vbo"].value == "true"); + bool interleave = (options["interleave"].value == "true"); + mesh_.vbo_update_method(Mesh::VBOUpdateMethodMap); + mesh_.interleave(interleave); + + if (useVbo_) { + mesh_.build_vbo(); + } + else { + mesh_.build_array(); + } + + // Calculate a projection matrix that is a good fit for the model + vec3 maxVec = model.maxVec(); + vec3 minVec = model.minVec(); + vec3 diffVec = maxVec - minVec; + centerVec_ = maxVec + minVec; + centerVec_ /= 2.0; + float diameter = diffVec.length(); + radius_ = diameter / 2; + float fovy = 2.0 * atanf(radius_ / (2.0 + radius_)); + fovy /= M_PI; + fovy *= 180.0; + float aspect(static_cast(canvas_.width())/static_cast(canvas_.height())); + 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; + } + + return true; +} +void +RefractPrivate::teardown() +{ + depthTarget_.teardown(); + program_.stop(); + program_.release(); + mesh_.reset(); +} + +void +RefractPrivate::update(double elapsedTime) +{ + rotation_ = rotationSpeed_ * elapsedTime; +} + +void +RefractPrivate::draw() +{ + // To perform the depth pass, set up the model-view transformation so + // that we're looking at the horse from the light position. That will + // give us the appropriate view for the shadow. + modelview_.push(); + modelview_.loadIdentity(); + modelview_.lookAt(lightPosition.x(), lightPosition.y(), lightPosition.z(), + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + modelview_.rotate(rotation_, 0.0f, 1.0f, 0.0f); + mat4 mvp(projection_.getCurrent()); + mvp *= modelview_.getCurrent(); + modelview_.pop(); + + // Enable the depth render target with our transformation and render. + depthTarget_.enable(mvp); + vector attrib_locations; + attrib_locations.push_back(depthTarget_.program()["position"].location()); + attrib_locations.push_back(depthTarget_.program()["normal"].location()); + mesh_.set_attrib_locations(attrib_locations); + if (useVbo_) { + mesh_.render_vbo(); + } + else { + mesh_.render_array(); + } + depthTarget_.disable(); + + // Ground rendering using the above generated texture... + //ground_.draw(); + + // Draw the "normal" view of the horse + modelview_.push(); + modelview_.translate(-centerVec_.x(), -centerVec_.y(), -(centerVec_.z() + 2.0 + radius_)); + modelview_.rotate(rotation_, 0.0f, 1.0f, 0.0f); + mvp = projection_.getCurrent(); + mvp *= modelview_.getCurrent(); + + program_.start(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_); + program_["DistanceMap"] = 0; + program_["ModelViewProjectionMatrix"] = mvp; + + // Load the NormalMatrix uniform in the shader. The NormalMatrix is the + // inverse transpose of the model view matrix. + mat4 normal_matrix(modelview_.getCurrent()); + normal_matrix.inverse().transpose(); + program_["NormalMatrix"] = normal_matrix; + attrib_locations.clear(); + attrib_locations.push_back(program_["position"].location()); + attrib_locations.push_back(program_["normal"].location()); + mesh_.set_attrib_locations(attrib_locations); + if (useVbo_) { + mesh_.render_vbo(); + } + else { + mesh_.render_array(); + } + + // Per-frame cleanup + modelview_.pop(); +} + diff --git a/src/scene-refract.h b/src/scene-refract.h new file mode 100644 index 0000000..2d61ab3 --- /dev/null +++ b/src/scene-refract.h @@ -0,0 +1,97 @@ +// +// Copyright © 2012 Linaro Limited +// +// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. +// +// glmark2 is free software: you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// glmark2. If not, see . +// +// Authors: +// Jesse Barker +// +#ifndef SCENE_REFRACT_ +#define SCENE_REFRACT_ + +#include "scene.h" +#include "stack.h" + +// +// To create a shadow map, we need a framebuffer object set up for a +// depth-only pass. The render target can then be bound as a texture, +// and the depth values sampled from that texture can be used in the +// distance-from-light computations when rendering the shadow on the +// ground below the rendered object. +// +class DistanceRenderTarget +{ + Program program_; + unsigned int canvas_width_; + unsigned int canvas_height_; + unsigned int width_; + unsigned int height_; + unsigned int tex_; + unsigned int fbo_; +public: + DistanceRenderTarget() : + canvas_width_(0), + canvas_height_(0), + width_(0), + height_(0), + tex_(0), + fbo_(0) {} + ~DistanceRenderTarget() {} + bool setup(unsigned int width, unsigned int height); + void teardown(); + void enable(const LibMatrix::mat4& mvp); + void disable(); + unsigned int texture() { return tex_; } + Program& program() { return program_; } +}; + +class RefractPrivate +{ + Canvas& canvas_; + DistanceRenderTarget depthTarget_; + Program program_; + LibMatrix::Stack4 modelview_; + LibMatrix::Stack4 projection_; + Mesh mesh_; + LibMatrix::vec3 centerVec_; + bool orientModel_; + float orientationAngle_; + LibMatrix::vec3 orientationVec_; + float radius_; + float rotation_; + float rotationSpeed_; + unsigned int texture_; + bool useVbo_; + +public: + RefractPrivate(Canvas& canvas) : + canvas_(canvas), + orientModel_(false), + orientationAngle_(0.0), + radius_(0.0), + rotation_(0.0), + rotationSpeed_(36.0), + texture_(0), + useVbo_(true) {} + ~RefractPrivate() {} + + bool setup(std::map& options); + void teardown(); + void update(double elapsedTime); + void draw(); +}; + +#endif // SCENE_REFRACT_ diff --git a/src/scene.h b/src/scene.h index dd77ba9..88f839d 100644 --- a/src/scene.h +++ b/src/scene.h @@ -574,4 +574,21 @@ public: ValidationResult validate(); }; +class RefractPrivate; +class SceneRefract : public Scene +{ + RefractPrivate* priv_; +public: + SceneRefract(Canvas& canvas); + ~SceneRefract(); + bool supported(bool show_errors); + bool load(); + void unload(); + bool setup(); + void teardown(); + void update(); + void draw(); + ValidationResult validate(); +}; + #endif -- cgit v1.2.3 From d474844c82efd39efe97cc1d182c6d0661408c3b Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Mon, 10 Dec 2012 15:17:15 -0800 Subject: SceneRefract: Updates to compute refraction vectors through the front and back of the object. This required adding a color target for the first pass so that we can store the surface normals from the back side of the object. Still need to determine whether or not to factor in the distance from the front to the back of the object (else the distance map may not be needed and we may not need the depth target in the first pass). --- data/shaders/light-refract.frag | 31 +++++++++++++++------- data/shaders/light-refract.vert | 5 ++++ src/scene-refract.cpp | 59 ++++++++++++++++++++++++++++++----------- src/scene-refract.h | 17 +++++++++--- 4 files changed, 83 insertions(+), 29 deletions(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index f7ae395..cc04071 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -1,24 +1,35 @@ uniform sampler2D DistanceMap; +uniform sampler2D NormalMap; +uniform sampler2D ImageMap; varying vec3 vertex_normal; varying vec4 vertex_position; +varying vec4 MapCoord; void main() { - const vec4 lightAmbient = vec4(0.1, 0.1, 0.1, 1.0); const vec4 lightSpecular = vec4(0.8, 0.8, 0.8, 1.0); - const vec4 matAmbient = vec4(0.2, 0.2, 0.2, 1.0); const vec4 matSpecular = vec4(1.0, 1.0, 1.0, 1.0); const float matShininess = 100.0; - vec3 eye_direction = normalize(-vertex_position.xyz); - vec3 light_direction = normalize(LightSourcePosition.xyz/LightSourcePosition.w - - vertex_position.xyz/vertex_position.w); + const vec2 point_five = vec2(0.5); + // Need the normalized light direction and surface normal vectors to + // compute the refraction vector through the "front" surface of the object. + vec3 light_direction = normalize(vertex_position.xyz/vertex_position.w - + LightSourcePosition.xyz/LightSourcePosition.w); vec3 normalized_normal = normalize(vertex_normal); - vec3 reflection = reflect(-light_direction, normalized_normal); + vec3 front_refraction = refract(light_direction, normalized_normal, 1.5); + // Offset the base map coordinate by the refaction vector, and re-normalize + // to texture coordinate space [0, 1]. + vec2 normcoord = (MapCoord.st + front_refraction.st + point_five) * point_five; + vec4 back_normal = texture2D(NormalMap, normcoord); + // Now refract again, using the minus normal from the lookup. + vec3 back_refraction = refract(front_refraction, -back_normal.xyz, 1.5); + vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; + vec4 texel = texture2D(ImageMap, imagecoord); + // Add in a specular component + vec3 reflection = reflect(light_direction, normalized_normal); + vec3 eye_direction = normalize(-vertex_position.xyz); float specularTerm = pow(max(0.0, dot(reflection, eye_direction)), matShininess); - float diffuseTerm = max(0.0, dot(normalized_normal, light_direction)); vec4 specular = (lightSpecular * matSpecular); - vec4 ambient = (lightAmbient * matAmbient); - vec4 diffuse = (LightColor * MaterialDiffuse); - gl_FragColor = (specular * specularTerm) + ambient + (diffuse * diffuseTerm); + gl_FragColor = (specular * specularTerm) + texel; } diff --git a/data/shaders/light-refract.vert b/data/shaders/light-refract.vert index 8a95ca7..9beeb9c 100644 --- a/data/shaders/light-refract.vert +++ b/data/shaders/light-refract.vert @@ -4,9 +4,11 @@ attribute vec3 normal; uniform mat4 ModelViewProjectionMatrix; uniform mat4 NormalMatrix; uniform mat4 ModelViewMatrix; +uniform mat4 LightMatrix; varying vec3 vertex_normal; varying vec4 vertex_position; +varying vec4 MapCoord; void main(void) { @@ -18,6 +20,9 @@ void main(void) // Transform the current position to eye coordinates vertex_position = ModelViewMatrix * current_position; + // Transform the current position for use as texture coordinates + MapCoord = LightMatrix * current_position; + // Transform the current position to clip coordinates gl_Position = ModelViewProjectionMatrix * current_position; } diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index b1d8dcc..aca59a8 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -33,7 +33,7 @@ using LibMatrix::mat4; using LibMatrix::vec4; using LibMatrix::vec3; -static const vec4 lightPosition(0.0f, 3.0f, 2.0f, 1.0f); +static const vec4 lightPosition(1.0f, 1.0f, 2.0f, 1.0f); // // Public interfaces @@ -193,20 +193,29 @@ DistanceRenderTarget::setup(unsigned int width, unsigned int height) return false; } - glGenTextures(1, &tex_); - glBindTexture(GL_TEXTURE_2D, tex_); + glGenTextures(2, &tex_[0]); + glBindTexture(GL_TEXTURE_2D, tex_[DEPTH]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width_, height_, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); + glBindTexture(GL_TEXTURE_2D, tex_[COLOR]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &fbo_); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, - tex_, 0); + tex_[DEPTH], 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_[COLOR], 0); unsigned int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { Log::error("DepthRenderState::setup: glCheckFramebufferStatus failed (0x%x)\n", status); @@ -223,8 +232,8 @@ DistanceRenderTarget::teardown() program_.stop(); program_.release(); if (tex_) { - glDeleteTextures(1, &tex_); - tex_ = 0; + glDeleteTextures(2, &tex_[0]); + tex_[DEPTH] = tex_[COLOR] = 0; } if (fbo_) { glDeleteFramebuffers(1, &fbo_); @@ -239,17 +248,17 @@ DistanceRenderTarget::enable(const mat4& mvp) program_["ModelViewProjectionMatrix"] = mvp; glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, - tex_, 0); + tex_[DEPTH], 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_[COLOR], 0); glViewport(0, 0, width_, height_); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } void DistanceRenderTarget::disable() { glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, canvas_width_, canvas_height_); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } bool @@ -258,8 +267,8 @@ RefractPrivate::setup(map& options) // Program object setup static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.vert"); static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.frag"); - static const vec4 materialDiffuse(0.0f, 0.0f, 0.0f, 0.0f); - static const vec4 lightColor(1.0, 1.0, 1.0, 1.0); + static const vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 0.0f); + static const vec4 lightColor(0.4, 0.4, 0.4, 1.0); ShaderSource vtx_source(vtx_shader_filename); ShaderSource frg_source(frg_shader_filename); @@ -344,7 +353,17 @@ RefractPrivate::setup(map& options) fovy /= M_PI; fovy *= 180.0; float aspect(static_cast(canvas_.width())/static_cast(canvas_.height())); - projection_.perspective(fovy, aspect, 2.0, 50.0); + projection_.perspective(fovy, aspect, 2.0, 2.0 + diameter); + + // Set up the light matrix with a bias that will convert values + // in the range of [-1, 1] to [0, 1)], then add in the projection + // and the "look at" matrix from the light position. + light_ *= LibMatrix::Mat4::translate(0.5, 0.5, 0.5); + light_ *= LibMatrix::Mat4::scale(0.5, 0.5, 0.5); + light_ *= projection_.getCurrent(); + light_ *= LibMatrix::Mat4::lookAt(lightPosition.x(), lightPosition.y(), lightPosition.z(), + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); if (!depthTarget_.setup(canvas_.width(), canvas_.height())) { Log::error("Failed to set up the render target for the depth pass\n"); @@ -385,6 +404,7 @@ RefractPrivate::draw() modelview_.pop(); // Enable the depth render target with our transformation and render. + glCullFace(GL_FRONT); depthTarget_.enable(mvp); vector attrib_locations; attrib_locations.push_back(depthTarget_.program()["position"].location()); @@ -397,6 +417,7 @@ RefractPrivate::draw() mesh_.render_array(); } depthTarget_.disable(); + glCullFace(GL_BACK); // Ground rendering using the above generated texture... //ground_.draw(); @@ -410,15 +431,23 @@ RefractPrivate::draw() program_.start(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture_); + glBindTexture(GL_TEXTURE_2D, depthTarget_.depthTexture()); program_["DistanceMap"] = 0; + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, depthTarget_.colorTexture()); + program_["NormalMap"] = 1; + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, texture_); + program_["ImageMap"] = 2; + // Load both the modelview*projection as well as the modelview matrix itself program_["ModelViewProjectionMatrix"] = mvp; - + program_["ModelViewMatrix"] = modelview_.getCurrent(); // Load the NormalMatrix uniform in the shader. The NormalMatrix is the // inverse transpose of the model view matrix. mat4 normal_matrix(modelview_.getCurrent()); normal_matrix.inverse().transpose(); program_["NormalMatrix"] = normal_matrix; + program_["LightMatrix"] = light_; attrib_locations.clear(); attrib_locations.push_back(program_["position"].location()); attrib_locations.push_back(program_["normal"].location()); diff --git a/src/scene-refract.h b/src/scene-refract.h index 2d61ab3..660678b 100644 --- a/src/scene-refract.h +++ b/src/scene-refract.h @@ -34,12 +34,17 @@ // class DistanceRenderTarget { + enum + { + DEPTH = 0, + COLOR + }; Program program_; unsigned int canvas_width_; unsigned int canvas_height_; unsigned int width_; unsigned int height_; - unsigned int tex_; + unsigned int tex_[2]; unsigned int fbo_; public: DistanceRenderTarget() : @@ -47,14 +52,17 @@ public: canvas_height_(0), width_(0), height_(0), - tex_(0), - fbo_(0) {} + fbo_(0) + { + tex_[DEPTH] = tex_[COLOR] = 0; + } ~DistanceRenderTarget() {} bool setup(unsigned int width, unsigned int height); void teardown(); void enable(const LibMatrix::mat4& mvp); void disable(); - unsigned int texture() { return tex_; } + unsigned int depthTexture() { return tex_[DEPTH]; } + unsigned int colorTexture() { return tex_[COLOR]; } Program& program() { return program_; } }; @@ -65,6 +73,7 @@ class RefractPrivate Program program_; LibMatrix::Stack4 modelview_; LibMatrix::Stack4 projection_; + LibMatrix::mat4 light_; Mesh mesh_; LibMatrix::vec3 centerVec_; bool orientModel_; -- cgit v1.2.3 From 711afadffe53d151872c160c9db64357bce6ef4b Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 11 Dec 2012 10:01:04 -0800 Subject: SceneRefract: Fix the back normal orientation (artifact from a previous hack on the depth pass shader). --- data/shaders/light-refract.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index cc04071..1dcd751 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -23,7 +23,7 @@ void main() vec2 normcoord = (MapCoord.st + front_refraction.st + point_five) * point_five; vec4 back_normal = texture2D(NormalMap, normcoord); // Now refract again, using the minus normal from the lookup. - vec3 back_refraction = refract(front_refraction, -back_normal.xyz, 1.5); + vec3 back_refraction = refract(front_refraction, back_normal.xyz, 1.5); vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; vec4 texel = texture2D(ImageMap, imagecoord); // Add in a specular component -- cgit v1.2.3 From e111ecb6f946b4bbe22ed7b3d26437aa175c5fbe Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 11 Dec 2012 10:08:49 -0800 Subject: SceneRefract: Use the eye direction, rather than the light direction as the incident vector for the front facing refraction. The light direction is still used to compute surface reflection for the specular component. --- data/shaders/light-refract.frag | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index 1dcd751..184ba29 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -12,12 +12,11 @@ void main() const vec4 matSpecular = vec4(1.0, 1.0, 1.0, 1.0); const float matShininess = 100.0; const vec2 point_five = vec2(0.5); - // Need the normalized light direction and surface normal vectors to + // Need the normalized eye direction and surface normal vectors to // compute the refraction vector through the "front" surface of the object. - vec3 light_direction = normalize(vertex_position.xyz/vertex_position.w - - LightSourcePosition.xyz/LightSourcePosition.w); + vec3 eye_direction = normalize(-vertex_position.xyz); vec3 normalized_normal = normalize(vertex_normal); - vec3 front_refraction = refract(light_direction, normalized_normal, 1.5); + vec3 front_refraction = refract(eye_direction, normalized_normal, 1.5); // Offset the base map coordinate by the refaction vector, and re-normalize // to texture coordinate space [0, 1]. vec2 normcoord = (MapCoord.st + front_refraction.st + point_five) * point_five; @@ -27,8 +26,9 @@ void main() vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; vec4 texel = texture2D(ImageMap, imagecoord); // Add in a specular component + vec3 light_direction = normalize(vertex_position.xyz/vertex_position.w - + LightSourcePosition.xyz/LightSourcePosition.w); vec3 reflection = reflect(light_direction, normalized_normal); - vec3 eye_direction = normalize(-vertex_position.xyz); float specularTerm = pow(max(0.0, dot(reflection, eye_direction)), matShininess); vec4 specular = (lightSpecular * matSpecular); gl_FragColor = (specular * specularTerm) + texel; -- cgit v1.2.3 From 916c6886409526451393a716cfd69e6db708ed5a Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 11 Dec 2012 10:18:53 -0800 Subject: SceneRefract: Add the model orientation step to the scene draw. --- src/scene-refract.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index aca59a8..fcbb863 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -202,7 +202,7 @@ DistanceRenderTarget::setup(unsigned int width, unsigned int height) glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width_, height_, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); glBindTexture(GL_TEXTURE_2D, tex_[COLOR]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -399,6 +399,10 @@ RefractPrivate::draw() 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); modelview_.rotate(rotation_, 0.0f, 1.0f, 0.0f); + if (orientModel_) + { + modelview_.rotate(orientationAngle_, orientationVec_.x(), orientationVec_.y(), orientationVec_.z()); + } mat4 mvp(projection_.getCurrent()); mvp *= modelview_.getCurrent(); modelview_.pop(); @@ -426,6 +430,10 @@ RefractPrivate::draw() modelview_.push(); modelview_.translate(-centerVec_.x(), -centerVec_.y(), -(centerVec_.z() + 2.0 + radius_)); modelview_.rotate(rotation_, 0.0f, 1.0f, 0.0f); + if (orientModel_) + { + modelview_.rotate(orientationAngle_, orientationVec_.x(), orientationVec_.y(), orientationVec_.z()); + } mvp = projection_.getCurrent(); mvp *= modelview_.getCurrent(); -- cgit v1.2.3 From 6f52195da3b55bf19e8f9093b73cc45e9a0288f8 Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 11 Dec 2012 11:09:55 -0800 Subject: SceneRefract: Index of refraction exiting the back of the object is back into "air", so make it so. --- data/shaders/light-refract.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index 184ba29..b1b8562 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -22,7 +22,7 @@ void main() vec2 normcoord = (MapCoord.st + front_refraction.st + point_five) * point_five; vec4 back_normal = texture2D(NormalMap, normcoord); // Now refract again, using the minus normal from the lookup. - vec3 back_refraction = refract(front_refraction, back_normal.xyz, 1.5); + vec3 back_refraction = refract(front_refraction, back_normal.xyz, 1.0); vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; vec4 texel = texture2D(ImageMap, imagecoord); // Add in a specular component -- cgit v1.2.3 From 11732cabe90df44a62936c73ea406791323597c6 Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 11 Dec 2012 11:47:05 -0800 Subject: SceneRefract: Pull the face culling and depth func switches into the render target object. --- src/scene-refract.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index fcbb863..e7fa659 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -253,12 +253,16 @@ DistanceRenderTarget::enable(const mat4& mvp) tex_[COLOR], 0); glViewport(0, 0, width_, height_); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glCullFace(GL_FRONT); + glDepthFunc(GL_GREATER); } void DistanceRenderTarget::disable() { glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, canvas_width_, canvas_height_); + glCullFace(GL_BACK); + glDepthFunc(GL_LEQUAL); } bool @@ -408,7 +412,6 @@ RefractPrivate::draw() modelview_.pop(); // Enable the depth render target with our transformation and render. - glCullFace(GL_FRONT); depthTarget_.enable(mvp); vector attrib_locations; attrib_locations.push_back(depthTarget_.program()["position"].location()); @@ -421,10 +424,6 @@ RefractPrivate::draw() mesh_.render_array(); } depthTarget_.disable(); - glCullFace(GL_BACK); - - // Ground rendering using the above generated texture... - //ground_.draw(); // Draw the "normal" view of the horse modelview_.push(); -- cgit v1.2.3 From b44efa6db340d984a623f6d03d1f451c06050037 Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Wed, 12 Dec 2012 16:00:35 -0800 Subject: SceneRefract: What should be a more correct computation for the back refraction based upon an approximation of the projection of the front refraction to a point on the back of the object. Use that point to do the back refraction. --- data/shaders/light-refract.frag | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index b1b8562..f71a283 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -19,10 +19,14 @@ void main() vec3 front_refraction = refract(eye_direction, normalized_normal, 1.5); // Offset the base map coordinate by the refaction vector, and re-normalize // to texture coordinate space [0, 1]. - vec2 normcoord = (MapCoord.st + front_refraction.st + point_five) * point_five; - vec4 back_normal = texture2D(NormalMap, normcoord); - // Now refract again, using the minus normal from the lookup. - vec3 back_refraction = refract(front_refraction, back_normal.xyz, 1.0); + vec4 mc_perspective = MapCoord / MapCoord.w; + vec4 distance_value = texture2D(DistanceMap, mc_perspective.st); + float frontToBack = distance_value.z - mc_perspective.z; + vec3 back_position = (front_refraction - vertex_position) + frontToBack; + vec2 normcoord = (mc_perspective.st + front_refraction.st + point_five) * point_five; + vec3 back_normal = texture2D(NormalMap, normcoord).xyz; + // Now refract again, using the normal from the lookup. + vec3 back_refraction = refract(back_position, back_normal.xyz, 1.0); vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; vec4 texel = texture2D(ImageMap, imagecoord); // Add in a specular component -- cgit v1.2.3 From 90c50c723d9ee13bcd4cdc4f0284f2c246945095 Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Thu, 13 Dec 2012 14:21:57 -0800 Subject: SceneRefract: Final (hopefully) tweaks for computing the distance through the object (the set up of the depth texture, the rendering of the back-side pass, and sampling the depth map), and handling the projection of the transmitted vector through the object to the exit point. Also added some comments in the shader to explain the steps. --- data/shaders/light-refract.frag | 32 +++++++++++++++++++------------- src/scene-refract.cpp | 7 ++----- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index f71a283..bcc5096 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -13,23 +13,29 @@ void main() const float matShininess = 100.0; const vec2 point_five = vec2(0.5); // Need the normalized eye direction and surface normal vectors to - // compute the refraction vector through the "front" surface of the object. + // compute the transmitted vector through the "front" surface of the object. vec3 eye_direction = normalize(-vertex_position.xyz); vec3 normalized_normal = normalize(vertex_normal); - vec3 front_refraction = refract(eye_direction, normalized_normal, 1.5); - // Offset the base map coordinate by the refaction vector, and re-normalize - // to texture coordinate space [0, 1]. - vec4 mc_perspective = MapCoord / MapCoord.w; - vec4 distance_value = texture2D(DistanceMap, mc_perspective.st); - float frontToBack = distance_value.z - mc_perspective.z; - vec3 back_position = (front_refraction - vertex_position) + frontToBack; - vec2 normcoord = (mc_perspective.st + front_refraction.st + point_five) * point_five; + vec3 front_refraction = refract(eye_direction, normalized_normal, 1.45); + // Find our best distance approximation through the object so we can + // project the transmitted vector to the back of the object to find + // the exit point. + vec3 mc_perspective = (MapCoord.xyz / MapCoord.w) + front_refraction; + vec2 dcoord = mc_perspective.st * point_five + point_five; + vec4 distance_value = texture2D(DistanceMap, dcoord); + vec3 back_position = vertex_position.xyz + front_refraction * distance_value.z; + // Use the exit point to index the map of back-side normals, and use the + // back-side position and normal to find the transmitted vector out of the + // object. + vec2 normcoord = back_position.st * point_five + point_five; vec3 back_normal = texture2D(NormalMap, normcoord).xyz; - // Now refract again, using the normal from the lookup. - vec3 back_refraction = refract(back_position, back_normal.xyz, 1.0); - vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five; + vec3 back_refraction = refract(back_position, back_normal, 1.0); + // Use the transmitted vector from the exit point to determine where + // the vector would intersect the environment (in this case a background + // image. + vec2 imagecoord = back_refraction.st * point_five + point_five; vec4 texel = texture2D(ImageMap, imagecoord); - // Add in a specular component + // Add in specular reflection, and we have our fragment value. vec3 light_direction = normalize(vertex_position.xyz/vertex_position.w - LightSourcePosition.xyz/LightSourcePosition.w); vec3 reflection = reflect(light_direction, normalized_normal); diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index e7fa659..f4188e0 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -203,11 +203,12 @@ DistanceRenderTarget::setup(unsigned int width, unsigned int height) GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); glBindTexture(GL_TEXTURE_2D, tex_[COLOR]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &fbo_); @@ -254,7 +255,6 @@ DistanceRenderTarget::enable(const mat4& mvp) glViewport(0, 0, width_, height_); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glCullFace(GL_FRONT); - glDepthFunc(GL_GREATER); } void DistanceRenderTarget::disable() @@ -262,7 +262,6 @@ void DistanceRenderTarget::disable() glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, canvas_width_, canvas_height_); glCullFace(GL_BACK); - glDepthFunc(GL_LEQUAL); } bool @@ -271,7 +270,6 @@ RefractPrivate::setup(map& options) // Program object setup static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.vert"); static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.frag"); - static const vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 0.0f); static const vec4 lightColor(0.4, 0.4, 0.4, 1.0); ShaderSource vtx_source(vtx_shader_filename); @@ -279,7 +277,6 @@ RefractPrivate::setup(map& options) frg_source.add_const("LightColor", lightColor); frg_source.add_const("LightSourcePosition", lightPosition); - frg_source.add_const("MaterialDiffuse", materialDiffuse); if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { return false; -- cgit v1.2.3 From 6f808b75d48e5c8ed98fd103098a677ca9ce2e9b Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Thu, 13 Dec 2012 16:06:17 -0800 Subject: SceneRefract: Make the refractive index of the medium a command line option. The default is 1.2, but could be anything ("believable" effects are probably in the lower values). --- data/shaders/light-refract.frag | 2 +- src/scene-refract.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag index bcc5096..d1f1397 100644 --- a/data/shaders/light-refract.frag +++ b/data/shaders/light-refract.frag @@ -16,7 +16,7 @@ void main() // compute the transmitted vector through the "front" surface of the object. vec3 eye_direction = normalize(-vertex_position.xyz); vec3 normalized_normal = normalize(vertex_normal); - vec3 front_refraction = refract(eye_direction, normalized_normal, 1.45); + vec3 front_refraction = refract(eye_direction, normalized_normal, RefractiveIndex); // Find our best distance approximation through the object so we can // project the transmitted vector to the back of the object to find // the exit point. diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index f4188e0..b936362 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -77,6 +77,8 @@ SceneRefract::SceneRefract(Canvas& canvas) : } options_["texture"] = Scene::Option("texture", "nasa1", "Which texture to use", optionValues); + options_["index"] = Scene::Option("index", "1.2", + "Index of refraction of the medium to simulate"); options_["use-vbo"] = Scene::Option("use-vbo", "true", "Whether to use VBOs for rendering", "false,true"); @@ -277,6 +279,8 @@ RefractPrivate::setup(map& options) frg_source.add_const("LightColor", lightColor); frg_source.add_const("LightSourcePosition", lightPosition); + float refractive_index(Util::fromString(options["index"].value)); + frg_source.add_const("RefractiveIndex", refractive_index); if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { return false; -- cgit v1.2.3 From 3c0e8e2aefca4b74e6d387118c67b7bbe3622001 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Sat, 15 Dec 2012 11:46:12 +0200 Subject: SceneRefract: Fix potential memory leak The memory leak occurs when using the scene for multiple benchmarks. --- src/scene-refract.cpp | 6 +----- src/scene.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp index b936362..db0aec8 100644 --- a/src/scene-refract.cpp +++ b/src/scene-refract.cpp @@ -87,11 +87,6 @@ SceneRefract::SceneRefract(Canvas& canvas) : "false,true"); } -SceneRefract::~SceneRefract() -{ - delete priv_; -} - bool SceneRefract::supported(bool show_errors) { @@ -150,6 +145,7 @@ SceneRefract::teardown() { // Add scene-specific teardown here priv_->teardown(); + delete priv_; Scene::teardown(); } diff --git a/src/scene.h b/src/scene.h index 88f839d..66377e1 100644 --- a/src/scene.h +++ b/src/scene.h @@ -580,7 +580,6 @@ class SceneRefract : public Scene RefractPrivate* priv_; public: SceneRefract(Canvas& canvas); - ~SceneRefract(); bool supported(bool show_errors); bool load(); void unload(); -- cgit v1.2.3