Merge pull request #3293 from ey6es/metavoxels

Support for shadows on heightmaps.
This commit is contained in:
Philip Rosedale 2014-08-15 17:37:58 -07:00
commit 5ca28901bd
6 changed files with 190 additions and 13 deletions

View file

@ -20,6 +20,9 @@ uniform float heightScale;
// the scale between height and color textures
uniform float colorScale;
// the interpolated position
varying vec4 position;
// the interpolated normal
varying vec4 normal;
@ -32,13 +35,17 @@ void main(void) {
texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r;
normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0));
// pass along the scaled/offset texture coordinates
gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * colorScale;
// add the height to the position
float height = texture2D(heightMap, heightCoord).r;
gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0));
position = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0));
gl_Position = gl_ProjectionMatrix * position;
// the zero height should be invisible
gl_FrontColor = vec4(1.0, 1.0, 1.0, step(height, 0.0));
// pass along the scaled/offset texture coordinates
gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * colorScale;
// and the shadow texture coordinates
gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0);
}

View file

@ -0,0 +1,48 @@
#version 120
//
// metavoxel_heightfield.frag
// fragment shader
//
// Created by Andrzej Kapolka on 7/28/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the distances to the cascade sections
uniform vec3 shadowDistances;
// the inverse of the size of the shadow map
const float shadowScale = 1.0 / 2048.0;
// the interpolated position
varying vec4 position;
// the interpolated normal
varying vec4 normal;
void main(void) {
// compute the index of the cascade to use and the corresponding texture coordinates
int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0)));
vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position),
dot(gl_EyePlaneR[shadowIndex], position));
// compute the base color based on OpenGL lighting model
float diffuse = dot(normalize(normal), gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * 0.25 *
(shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r +
shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r);
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st);
}

View file

@ -0,0 +1,37 @@
#version 120
//
// metavoxel_heightfield.frag
// fragment shader
//
// Created by Andrzej Kapolka on 7/28/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the inverse of the size of the shadow map
const float shadowScale = 1.0 / 2048.0;
// the interpolated normal
varying vec4 normal;
void main(void) {
// compute the base color based on OpenGL lighting model
float diffuse = dot(normalize(normal), gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * 0.25 *
(shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, shadowScale, 0.0)).r);
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st);
}

View file

@ -760,10 +760,21 @@ void HeightfieldBuffer::render(bool cursor) {
glBindTexture(GL_TEXTURE_2D, _heightTextureID);
if (!cursor) {
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getHeightScaleLocation(), 1.0f / _heightSize);
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getColorScaleLocation(), (float)_heightSize / innerSize);
int heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation();
int colorScaleLocation = DefaultMetavoxelRendererImplementation::getColorScaleLocation();
ProgramObject* program = &DefaultMetavoxelRendererImplementation::getHeightfieldProgram();
if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) {
heightScaleLocation = DefaultMetavoxelRendererImplementation::getShadowMapHeightScaleLocation();
colorScaleLocation = DefaultMetavoxelRendererImplementation::getShadowMapColorScaleLocation();
program = &DefaultMetavoxelRendererImplementation::getShadowMapHeightfieldProgram();
} else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
heightScaleLocation = DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightScaleLocation();
colorScaleLocation = DefaultMetavoxelRendererImplementation::getCascadedShadowMapColorScaleLocation();
program = &DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightfieldProgram();
}
program->setUniformValue(heightScaleLocation, 1.0f / _heightSize);
program->setUniformValue(colorScaleLocation, (float)_heightSize / innerSize);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
}
@ -858,6 +869,35 @@ void DefaultMetavoxelRendererImplementation::init() {
_colorScaleLocation = _heightfieldProgram.uniformLocation("colorScale");
_heightfieldProgram.release();
_shadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield.vert");
_shadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_heightfield_shadow_map.frag");
_shadowMapHeightfieldProgram.link();
_shadowMapHeightfieldProgram.bind();
_shadowMapHeightfieldProgram.setUniformValue("heightMap", 0);
_shadowMapHeightfieldProgram.setUniformValue("diffuseMap", 1);
_shadowMapHeightfieldProgram.setUniformValue("shadowMap", 2);
_shadowMapHeightScaleLocation = _shadowMapHeightfieldProgram.uniformLocation("heightScale");
_shadowMapColorScaleLocation = _shadowMapHeightfieldProgram.uniformLocation("colorScale");
_shadowMapHeightfieldProgram.release();
_cascadedShadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield.vert");
_cascadedShadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cascaded_shadow_map.frag");
_cascadedShadowMapHeightfieldProgram.link();
_cascadedShadowMapHeightfieldProgram.bind();
_cascadedShadowMapHeightfieldProgram.setUniformValue("heightMap", 0);
_cascadedShadowMapHeightfieldProgram.setUniformValue("diffuseMap", 1);
_cascadedShadowMapHeightfieldProgram.setUniformValue("shadowMap", 2);
_cascadedShadowMapHeightScaleLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("heightScale");
_cascadedShadowMapColorScaleLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("colorScale");
_shadowDistancesLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("shadowDistances");
_cascadedShadowMapHeightfieldProgram.release();
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cursor.vert");
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
@ -1394,15 +1434,34 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
_heightfieldProgram.bind();
ProgramObject* program = &_heightfieldProgram;
if (Menu::getInstance()->getShadowsEnabled()) {
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
program = &_cascadedShadowMapHeightfieldProgram;
program->bind();
program->setUniform(_shadowDistancesLocation, Application::getInstance()->getShadowDistances());
} else {
program = &_shadowMapHeightfieldProgram;
}
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
glActiveTexture(GL_TEXTURE0);
}
program->bind();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
data.guide(heightfieldRenderVisitor);
_heightfieldProgram.release();
program->release();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
@ -1416,6 +1475,13 @@ int DefaultMetavoxelRendererImplementation::_pointScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram;
int DefaultMetavoxelRendererImplementation::_heightScaleLocation;
int DefaultMetavoxelRendererImplementation::_colorScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_shadowMapHeightfieldProgram;
int DefaultMetavoxelRendererImplementation::_shadowMapHeightScaleLocation;
int DefaultMetavoxelRendererImplementation::_shadowMapColorScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_cascadedShadowMapHeightfieldProgram;
int DefaultMetavoxelRendererImplementation::_cascadedShadowMapHeightScaleLocation;
int DefaultMetavoxelRendererImplementation::_cascadedShadowMapColorScaleLocation;
int DefaultMetavoxelRendererImplementation::_shadowDistancesLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram;
static void enableClipPlane(GLenum plane, float x, float y, float z, float w) {

View file

@ -223,6 +223,14 @@ public:
static int getHeightScaleLocation() { return _heightScaleLocation; }
static int getColorScaleLocation() { return _colorScaleLocation; }
static ProgramObject& getShadowMapHeightfieldProgram() { return _shadowMapHeightfieldProgram; }
static int getShadowMapHeightScaleLocation() { return _shadowMapHeightScaleLocation; }
static int getShadowMapColorScaleLocation() { return _shadowMapColorScaleLocation; }
static ProgramObject& getCascadedShadowMapHeightfieldProgram() { return _cascadedShadowMapHeightfieldProgram; }
static int getCascadedShadowMapHeightScaleLocation() { return _cascadedShadowMapHeightScaleLocation; }
static int getCascadedShadowMapColorScaleLocation() { return _cascadedShadowMapColorScaleLocation; }
static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; }
Q_INVOKABLE DefaultMetavoxelRendererImplementation();
@ -240,6 +248,15 @@ private:
static int _heightScaleLocation;
static int _colorScaleLocation;
static ProgramObject _shadowMapHeightfieldProgram;
static int _shadowMapHeightScaleLocation;
static int _shadowMapColorScaleLocation;
static ProgramObject _cascadedShadowMapHeightfieldProgram;
static int _cascadedShadowMapHeightScaleLocation;
static int _cascadedShadowMapColorScaleLocation;
static int _shadowDistancesLocation;
static ProgramObject _heightfieldCursorProgram;
};

View file

@ -1449,9 +1449,11 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re
if (cascadedShadows) {
activeProgram->setUniform(activeLocations->shadowDistances, Application::getInstance()->getShadowDistances());
}
activeProgram->setUniformValueArray(activeLocations->localLightDirections,
(const GLfloat*)_localLightDirections, MAX_LOCAL_LIGHTS, 4);
if (mode != SHADOW_RENDER_MODE) {
activeProgram->setUniformValueArray(activeLocations->localLightDirections,
(const GLfloat*)_localLightDirections, MAX_LOCAL_LIGHTS, 4);
}
if (mesh.blendshapes.isEmpty()) {
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);