mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 16:13:28 +02:00
separate the rendering of the light outline from the main rendering and introduce a way to support both platform
This commit is contained in:
parent
c72b330821
commit
a378a6eccb
7 changed files with 221 additions and 10 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -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@>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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@>
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
153
libraries/render-utils/src/local_lights_drawOutline.slf
Normal file
153
libraries/render-utils/src/local_lights_drawOutline.slf
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue