separate the rendering of the light outline from the main rendering and introduce a way to support both platform

This commit is contained in:
samcake 2016-10-03 18:28:44 -07:00
parent c72b330821
commit a378a6eccb
7 changed files with 221 additions and 10 deletions

View file

@ -36,6 +36,7 @@
#include "directional_skybox_light_shadow_frag.h"
#include "local_lights_shading_frag.h"
#include "local_lights_drawOutline_frag.h"
#include "point_light_frag.h"
#include "spot_light_frag.h"
@ -103,6 +104,7 @@ void DeferredLightingEffect::init() {
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
_localLightLocations = std::make_shared<LightLocations>();
_localLightOutlineLocations = std::make_shared<LightLocations>();
_pointLightLocations = std::make_shared<LightLocations>();
_spotLightLocations = std::make_shared<LightLocations>();
@ -115,6 +117,7 @@ void DeferredLightingEffect::init() {
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations);
loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations);
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, false, _pointLightBack, _pointLightLocations);
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, true, _pointLightFront, _pointLightLocations);
@ -795,6 +798,14 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast<const float*>(&textureFrameTransform));
batch.draw(gpu::TRIANGLE_STRIP, 4);
// Draw outline as well ?
if (lightingModel->isShowLightContourEnabled()) {
batch.setPipeline(deferredLightingEffect->_localLightOutline);
batch._glUniform4fv(deferredLightingEffect->_localLightOutlineLocations->texcoordFrameTransform, 1, reinterpret_cast<const float*>(&textureFrameTransform));
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
}
}
}

View file

@ -90,6 +90,7 @@ private:
gpu::PipelinePointer _directionalLightShadow;
gpu::PipelinePointer _localLight;
gpu::PipelinePointer _localLightOutline;
gpu::PipelinePointer _pointLightBack;
gpu::PipelinePointer _pointLightFront;
@ -105,6 +106,7 @@ private:
LightLocationsPtr _directionalLightShadowLocations;
LightLocationsPtr _localLightLocations;
LightLocationsPtr _localLightOutlineLocations;
LightLocationsPtr _pointLightLocations;
LightLocationsPtr _spotLightLocations;

View file

@ -49,20 +49,24 @@ float projection_getFar(mat4 projection) {
<@if GLPROFILE == MAC_GL @>
#define GRID_NUM_ELEMENTS 4096
#define GRID_INDEX_TYPE ivec4
#define GRID_FETCH_BUFFER(i) i / 4][i % 4
<@else@>
#define GRID_NUM_ELEMENTS 16384
#define GRID_INDEX_TYPE int
#define GRID_FETCH_BUFFER(i) i
<@endif@>
uniform clusterGridBuffer {
int _clusterGridTable[GRID_NUM_ELEMENTS];
GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];
};
uniform clusterContentBuffer {
int _clusterGridContent[GRID_NUM_ELEMENTS];
GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];
};
ivec3 clusterGrid_getCluster(int index) {
int clusterDesc = _clusterGridTable[index];
int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];
int numPointLights = 0xFF & (clusterDesc >> 16);
int numSpotLights = 0xFF & (clusterDesc >> 24);
int contentOffset = 0xFFFF & (clusterDesc);
@ -70,12 +74,11 @@ ivec3 clusterGrid_getCluster(int index) {
}
int clusterGrid_getClusterLightId(int index, int offset) {
int arrayElement = offset + index;
int element = _clusterGridContent[arrayElement];
int elementIndex = offset + index;
int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];
return element;
// int element = _clusterGridContent[arrayElement >> 1];
// return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;
//int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];
// return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;
}
<@endif@>

View file

@ -50,3 +50,24 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,
<@endfunc@>
<@func declareDrawPointOutline()@>
bool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 fragEyeDir) {
// Allright we re valid in the volume
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
// Show edges
float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);
if (edge < 1) {
float edgeCoord = exp2(-8.0*edge*edge);
color = vec3(edgeCoord * edgeCoord * getLightColor(light));
}
return (edge < 1);
}
<@endfunc@>

View file

@ -54,4 +54,26 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,
<@endfunc@>
<@func declareDrawSpotOutline()@>
bool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir) {
// Allright we re valid in the volume
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
// Show edges
float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);
float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));
float edgeDist = min(edgeDistR, edgeDistS);
float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);
if (edge < 1) {
float edgeCoord = exp2(-8.0*edge*edge);
color = vec3(edgeCoord * edgeCoord * getLightColor(light));
}
return (edge < 1);
}
<@endfunc@>

View file

@ -143,8 +143,7 @@ public:
bool enablePointLight{ true };
bool enableSpotLight{ true };
// bool showLightContour { false }; // false by default
bool showLightContour { true }; // false by default
bool showLightContour { false }; // false by default
signals:
void dirty();

View file

@ -0,0 +1,153 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// local_lights_drawOutline.frag
// fragment shader
//
// Created by Sam Gateau on 9/6/2016.
// 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
//
// Everything about deferred buffer
<@include DeferredBufferRead.slh@>
<$declareDeferredCurvature()$>
// Everything about light
<@include model/Light.slh@>
<$declareLightBuffer(128)$>
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareDrawPointOutline()$>
<@include LightSpot.slh@>
<$declareDrawSpotOutline()$>
<@include LightClusterGrid.slh@>
in vec2 _texCoord0;
out vec4 _fragColor;
void main(void) {
// Grab the fragment data from the uv
vec2 texCoord = _texCoord0.st;
vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);
DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);
if (frag.mode == FRAG_MODE_UNLIT) {
discard;
}
frag.position = fragPosition;
// Frag pos in world
mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition;
// From frag world pos find the cluster
vec4 clusterEyePos = frustumGrid_worldToEye(fragPos);
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
if (numLights <= 0) {
discard;
}
int lightClusterOffset = cluster.z;
ivec3 dims = frustumGrid.dims.xyz;
if (clusterPos.x < 0 || clusterPos.x >= dims.x) {
discard;
}
if (clusterPos.y < 0 || clusterPos.y >= dims.y) {
discard;
}
if (clusterPos.z < 0 || clusterPos.z > dims.z) {
discard;
}
// Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
int numLightTouching = 0;
for (int i = 0; i < cluster.x; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
Light light = getLight(theLightIndex);
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
vec4 fragLightDirLen;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
continue;
}
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {
continue;
}
numLightTouching++;
// Allright we re valid in the volume
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
vec3 color = vec3(0.0);
if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) {
_fragColor.rgb += color;
}
}
for (int i = cluster.x; i < numLights; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
Light light = getLight(theLightIndex);
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
vec4 fragLightDirLen;
float cosSpotAngle;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
continue;
}
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {
continue;
}
// Check spot
if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {
continue;
}
numLightTouching++;
vec3 color = vec3(0.0);
if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) {
_fragColor.rgb += color;
}
}
}