# Conflicts:
#	indra/llrender/llrender2dutils.cpp
#	indra/newview/llreflectionmapmanager.cpp
#	indra/newview/llviewershadermgr.cpp
#	indra/newview/llviewershadermgr.h
master
Ansariel 2022-09-20 11:37:09 +02:00
commit 87501c03ae
33 changed files with 844 additions and 771 deletions

View File

@ -1576,7 +1576,14 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
else
{ // platforms with working drivers...
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
// We just want GL_ALPHA, but that isn't supported in OGL core profile 4.
static const size_t TEMP_BYTES_PER_PIXEL = 4;
U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data);
for (size_t pixel = 0; pixel < pixels; pixel++) {
alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3];
}
ll_aligned_free_32(temp_data);
}
}
else

View File

@ -1067,13 +1067,6 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#endif
#if defined(TRACY_ENABLE) && LL_PROFILER_ENABLE_TRACY_OPENGL
// Tracy uses the following:
// glGenQueries
// glGetQueryiv
// glGetQueryObjectiv
#define glGenQueries glGenQueriesARB
#define glGetQueryiv glGetQueryivARB
#define glGetQueryObjectiv glGetQueryObjectivARB
#include <tracy/TracyOpenGL.hpp>
#endif

View File

@ -227,7 +227,6 @@ void LLGLSLShader::stopProfile(U32 count, U32 mode)
void LLGLSLShader::placeProfileQuery()
{
#if 1 || !LL_DARWIN
if (mTimerQuery == 0)
{
glGenQueries(1, &mSamplesQuery);
@ -269,12 +268,10 @@ void LLGLSLShader::placeProfileQuery()
glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery);
glBeginQuery(GL_TIME_ELAPSED, mTimerQuery);
#endif
}
void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
{
#if !LL_DARWIN
glEndQuery(GL_TIME_ELAPSED);
glEndQuery(GL_SAMPLES_PASSED);
@ -307,7 +304,6 @@ void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
sTotalDrawCalls++;
mDrawCalls++;
#endif
}
@ -679,7 +675,6 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar *)name);
#if !LL_DARWIN
if (size > 0)
{
switch(type)
@ -721,7 +716,6 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
}
mTotalUniformSize += size;
}
#endif
S32 location = glGetUniformLocation(mProgramObject, name);
if (location != -1)

View File

@ -897,11 +897,11 @@ void LLRender::init(bool needs_vertex_buffer)
}
// <FS:Ansariel> Don't ignore OpenGL max line width
GLint range[2];
glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range);
GLfloat range[2];
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
stop_glerror();
mMaxLineWidthAliased = F32(range[1]);
glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
stop_glerror();
mMaxLineWidthSmooth = F32(range[1]);
// </FS:Ansariel>

View File

@ -1966,7 +1966,15 @@ void LLRender2D::setLineWidth(F32 width)
{
// <FS> Line width OGL core profile fix by Rye Mutt
//gGL.flush();
//glLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));
//// If outside the allowed range, glLineWidth fails with "invalid value".
//// On Darwin, the range is [1, 1].
//static GLfloat range[2]{0.0};
//if (range[1] == 0)
//{
// glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
//}
//width *= lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f);
//glLineWidth(llclamp(width, range[0], range[1]));
gGL.setLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));
}

View File

@ -301,13 +301,11 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
mTex.push_back(tex);
mInternalFormat.push_back(color_fmt);
#if !LL_DARWIN
if (gDebugGL)
{ //bind and unbind to validate target
bindTarget();
flush();
}
#endif
return true;
@ -471,6 +469,7 @@ void LLRenderTarget::release()
void LLRenderTarget::bindTarget()
{
LL_PROFILE_GPU_ZONE("bindTarget");
llassert(mFBO);
if (mFBO)
@ -577,6 +576,7 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
void LLRenderTarget::flush(bool fetch_depth)
{
LL_PROFILE_GPU_ZONE("rt flush");
gGL.flush();
llassert(mFBO);
if (!mFBO)

View File

@ -1330,6 +1330,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
mReservedUniforms.push_back("emissiveRect");
mReservedUniforms.push_back("brdfLut");
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");

View File

@ -177,6 +177,7 @@ public:
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
DEFERRED_EMISSIVE, // "emissiveRect"
DEFERRED_BRDF_LUT, // "brdfLut"
DEFERRED_NOISE, // "noiseMap"
DEFERRED_LIGHTFUNC, // "lightFunc"
DEFERRED_LIGHT, // "lightMap"

View File

@ -1342,7 +1342,6 @@ void LLVertexBuffer::setupVertexArray()
if (attrib_integer[i])
{
#if !LL_DARWIN
//glVertexattribIPointer requires GLSL 1.30 or later
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
{
@ -1351,9 +1350,8 @@ void LLVertexBuffer::setupVertexArray()
// Cast via intptr_t to make it painfully obvious to the
// compiler that we're doing this intentionally.
glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i],
reinterpret_cast<const GLvoid*>(intptr_t(mOffsets[i])));
reinterpret_cast<const GLvoid*>(intptr_t(mOffsets[i])));
}
#endif
}
else
{
@ -2392,11 +2390,9 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
if (data_mask & MAP_TEXTURE_INDEX &&
(gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
{
#if !LL_DARWIN
S32 loc = TYPE_TEXTURE_INDEX;
void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
#endif
}
if (data_mask & MAP_VERTEX)
{
@ -2487,11 +2483,9 @@ void LLVertexBuffer::setupVertexBufferFast(U32 data_mask)
}
if (data_mask & MAP_TEXTURE_INDEX)
{
#if !LL_DARWIN
S32 loc = TYPE_TEXTURE_INDEX;
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12);
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
#endif
}
if (data_mask & MAP_VERTEX)
{

View File

@ -23,9 +23,35 @@
* $/LicenseInfo$
*/
/* Parts of this file are taken from Sascha Willem's Vulkan GLTF refernce implementation
MIT License
Copyright (c) 2018 Sascha Willems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
uniform sampler2D projectionMap; // rgba
uniform sampler2D brdfLut;
// projected lighted params
uniform mat4 proj_mat; //screen space to light space projector
@ -322,221 +348,150 @@ vec3 hue_to_rgb(float hue)
// PBR Utils
// ior Index of Refraction, normally 1.5
// returns reflect0
float calcF0(float ior)
vec2 BRDF(float NoV, float roughness)
{
float f0 = (1.0 - ior) / (1.0 + ior);
return f0 * f0;
}
vec3 fresnel(float vh, vec3 f0, vec3 f90 )
{
float x = 1.0 - abs(vh);
float x2 = x*x;
float x5 = x2*x2*x;
vec3 fr = f0 + (f90 - f0)*x5;
return fr;
}
vec3 fresnelSchlick( vec3 reflect0, vec3 reflect90, float vh)
{
return reflect0 + (reflect90 - reflect0) * pow(clamp(1.0 - vh, 0.0, 1.0), 5.0);
}
// Approximate Environment BRDF
vec2 getGGXApprox( vec2 uv )
{
// Reference: Physically Based Shading on Mobile
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
// EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
float nv = uv.x;
float roughness = uv.y;
const vec4 c0 = vec4( -1, -0.0275, -0.572, 0.022 );
const vec4 c1 = vec4( 1, 0.0425, 1.04 , -0.04 );
vec4 r = roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( -9.28 * nv ) ) * r.x + r.y;
vec2 ScaleBias = vec2( -1.04, 1.04 ) * a004 + r.zw;
return ScaleBias;
}
#define PBR_USE_GGX_APPROX 1
vec2 getGGX( vec2 brdfPoint )
{
#if PBR_USE_GGX_APPROX
return getGGXApprox( brdfPoint);
#else
return texture2D(GGXLUT, brdfPoint).rg; // TODO: use GGXLUT
#endif
}
// Reference: float getRangeAttenuation(float range, float distance)
float getLightAttenuationPointSpot(float range, float distance)
{
#if 1
return distance;
#else
float range2 = pow(range, 2.0);
// support negative range as unlimited
if (range <= 0.0)
{
return 1.0 / range2;
}
return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / range2;
#endif
}
vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance)
{
float rangeAttenuation = getLightAttenuationPointSpot(lightRange, lightDistance);
return rangeAttenuation * lightColor;
}
float getLightAttenuationSpot(vec3 spotDirection)
{
return 1.0;
}
vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v)
{
float spotAttenuation = getLightAttenuationSpot(-v);
return spotAttenuation * getLightIntensityPoint( lightColor, lightRange, lightDistance );
}
// NOTE: This is different from the GGX texture
float D_GGX( float nh, float alphaRough )
{
float rough2 = alphaRough * alphaRough;
float f = (nh * nh) * (rough2 - 1.0) + 1.0;
return rough2 / (M_PI * f * f);
}
// NOTE: This is different from the GGX texture
// See:
// Real Time Rendering, 4th Edition
// Page 341
// Equation 9.43
// Also see:
// https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg)
// 4.4.2 Geometric Shadowing (specular G)
float V_GGX( float nl, float nv, float alphaRough )
{
#if 1
// Note: When roughness is zero, has discontuinity in the bottom hemisphere
float rough2 = alphaRough * alphaRough;
float ggxv = nl * sqrt(nv * nv * (1.0 - rough2) + rough2);
float ggxl = nv * sqrt(nl * nl * (1.0 - rough2) + rough2);
float ggx = ggxv + ggxl;
if (ggx > 0.0)
{
return 0.5 / ggx;
}
return 0.0;
#else
// See: smithVisibility_GGXCorrelated, V_SmithCorrelated, etc.
float rough2 = alphaRough * alphaRough;
float ggxv = nl * sqrt(nv * (nv - rough2 * nv) + rough2);
float ggxl = nv * sqrt(nl * (nl - rough2 * nl) + rough2);
return 0.5 / (ggxv + ggxl);
#endif
}
// NOTE: Assumes a hard-coded IOR = 1.5
void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight )
{
float metal = packedORM.b;
c_diff = mix(diffuse, vec3(0), metal);
float IOR = 1.5; // default Index Of Refraction 1.5 (dielectrics)
reflect0 = vec3(0.04); // -> incidence reflectance 0.04
// reflect0 = vec3(calcF0(IOR));
reflect0 = mix(reflect0, diffuse, metal); // reflect at 0 degrees
reflect90 = vec3(1); // reflect at 90 degrees
specWeight = 1.0;
// When roughness is zero blender shows a tiny specular
float perceptualRough = max(packedORM.g, 0.1);
alphaRough = perceptualRough * perceptualRough;
}
vec3 BRDFDiffuse(vec3 color)
{
return color * ONE_OVER_PI;
}
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh )
{
return (1.0 - fresnelSchlick( reflect0, reflect90, vh)) * BRDFDiffuse(c_diff);
}
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRough, float specWeight, float vh, float nl, float nv, float nh )
{
vec3 fresnel = fresnelSchlick( reflect0, reflect90, vh ); // Fresnel
float vis = V_GGX( nl, nv, alphaRough ); // Visibility
float d = D_GGX( nh, alphaRough ); // Distribution
return fresnel * vis * d;
return texture(brdfLut, vec2(NoV, roughness)).rg;
}
// set colorDiffuse and colorSpec to the results of GLTF PBR style IBL
void pbrIbl(out vec3 colorDiffuse, // diffuse color output
out vec3 colorSpec, // specular color output,
vec3 pbrIbl(vec3 diffuseColor,
vec3 specularColor,
vec3 radiance, // radiance map sample
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv, // normal dot view vector
float perceptualRough, // roughness factor
float gloss, // 1.0 - roughness factor
vec3 reflect0, // see also: initMaterial
vec3 c_diff)
float perceptualRough)
{
// Common to RadianceGGX and RadianceLambertian
vec2 brdfPoint = clamp(vec2(nv, perceptualRough), vec2(0,0), vec2(1,1));
vec2 vScaleBias = getGGX( brdfPoint); // Environment BRDF: scale and bias applied to reflect0
vec3 fresnelR = max(vec3(gloss), reflect0) - reflect0; // roughness dependent fresnel
vec3 kSpec = reflect0 + fresnelR*pow(1.0 - nv, 5.0);
// retrieve a scale and bias to F0. See [1], Figure 3
vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
vec3 diffuseLight = irradiance;
vec3 specularLight = radiance;
vec3 diffuse = diffuseLight * diffuseColor;
vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
vec3 FssEssGGX = kSpec*vScaleBias.x + vScaleBias.y;
colorSpec = radiance * FssEssGGX;
//specular *= 1.5;
// Reference: getIBLRadianceLambertian fs
vec3 FssEssLambert = kSpec * vScaleBias.x + vScaleBias.y; // NOTE: Very similar to FssEssRadiance but with extra specWeight term
float Ems = 1.0 - (vScaleBias.x + vScaleBias.y);
vec3 avg = (reflect0 + (1.0 - reflect0) / 21.0);
vec3 AvgEms = avg * Ems;
vec3 FmsEms = AvgEms * FssEssLambert / (1.0 - AvgEms);
vec3 kDiffuse = c_diff * (1.0 - FssEssLambert + FmsEms);
colorDiffuse = (FmsEms + kDiffuse) * irradiance;
colorDiffuse *= ao;
colorSpec *= ao;
return (diffuse + specular) * ao;
}
void pbrDirectionalLight(inout vec3 colorDiffuse,
inout vec3 colorSpec,
vec3 sunlit,
float scol,
vec3 reflect0,
vec3 reflect90,
vec3 c_diff,
float alphaRough,
float vh,
float nl,
float nv,
float nh)
// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
// of the shading terms, outlined in the Readme.MD Appendix.
struct PBRInfo
{
float scale = 16.0;
vec3 sunColor = sunlit * scale;
float NdotL; // cos angle between normal and light direction
float NdotV; // cos angle between normal and view direction
float NdotH; // cos angle between normal and half vector
float LdotH; // cos angle between light direction and half vector
float VdotH; // cos angle between view direction and half vector
float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
float metalness; // metallic value at the surface
vec3 reflectance0; // full reflectance color (normal incidence angle)
vec3 reflectance90; // reflectance color at grazing angle
float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
vec3 diffuseColor; // color contribution from diffuse lighting
vec3 specularColor; // color contribution from specular lighting
};
// scol = sun shadow
vec3 intensity = sunColor * nl * scol;
vec3 sunDiffuse = intensity * BRDFLambertian (reflect0, reflect90, c_diff , 1.0, vh);
vec3 sunSpec = intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, 1.0, vh, nl, nv, nh);
colorDiffuse += sunDiffuse;
colorSpec += sunSpec;
// Basic Lambertian diffuse
// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
// See also [1], Equation 1
vec3 diffuse(PBRInfo pbrInputs)
{
return pbrInputs.diffuseColor / M_PI;
}
// The following equation models the Fresnel reflectance term of the spec equation (aka F())
// Implementation of fresnel from [4], Equation 15
vec3 specularReflection(PBRInfo pbrInputs)
{
return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
}
// This calculates the specular geometric attenuation (aka G()),
// where rougher material will reflect less light back to the viewer.
// This implementation is based on [1] Equation 4, and we adopt their modifications to
// alphaRoughness as input as originally proposed in [2].
float geometricOcclusion(PBRInfo pbrInputs)
{
float NdotL = pbrInputs.NdotL;
float NdotV = pbrInputs.NdotV;
float r = pbrInputs.alphaRoughness;
float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
return attenuationL * attenuationV;
}
// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())
// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3.
float microfacetDistribution(PBRInfo pbrInputs)
{
float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
return roughnessSq / (M_PI * f * f);
}
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l) //surface point to light
{
// make sure specular highlights from punctual lights don't fall off of polished surfaces
perceptualRoughness = max(perceptualRoughness, 8.0/255.0);
float alphaRoughness = perceptualRoughness * perceptualRoughness;
// Compute reflectance.
float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
// For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
// For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
vec3 specularEnvironmentR0 = specularColor.rgb;
vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
vec3 h = normalize(l+v); // Half vector between both l and v
vec3 reflection = -normalize(reflect(v, n));
reflection.y *= -1.0f;
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);
PBRInfo pbrInputs = PBRInfo(
NdotL,
NdotV,
NdotH,
LdotH,
VdotH,
perceptualRoughness,
metallic,
specularEnvironmentR0,
specularEnvironmentR90,
alphaRoughness,
diffuseColor,
specularColor
);
// Calculate the shading terms for the microfacet specular shading model
vec3 F = specularReflection(pbrInputs);
float G = geometricOcclusion(pbrInputs);
float D = microfacetDistribution(pbrInputs);
const vec3 u_LightColor = vec3(1.0);
// Calculation of analytical lighting contribution
vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);
return color;
}

View File

@ -0,0 +1,141 @@
/**
* @file class1/deferred/genbrdflut.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
/* Taken from Sascha Willem's Vulkan GLTF refernce implementation
MIT License
Copyright (c) 2018 Sascha Willems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*[EXTRA_CODE_HERE]*/
VARYING vec2 vary_uv;
out vec4 outColor;
#define NUM_SAMPLES 1024
const float PI = 3.1415926536;
// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
float random(vec2 co)
{
float a = 12.9898;
float b = 78.233;
float c = 43758.5453;
float dt= dot(co.xy ,vec2(a,b));
float sn= mod(dt,3.14);
return fract(sin(sn) * c);
}
vec2 hammersley2d(uint i, uint N)
{
// Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
uint bits = (i << 16u) | (i >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
float rdi = float(bits) * 2.3283064365386963e-10;
return vec2(float(i) /float(N), rdi);
}
// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
{
// Maps a 2D point to a hemisphere with spread based on roughness
float alpha = roughness * roughness;
float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
// Tangent space
vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangentX = normalize(cross(up, normal));
vec3 tangentY = normalize(cross(normal, tangentX));
// Convert to world Space
return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
}
// Geometric Shadowing function
float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
{
float k = (roughness * roughness) / 2.0;
float GL = dotNL / (dotNL * (1.0 - k) + k);
float GV = dotNV / (dotNV * (1.0 - k) + k);
return GL * GV;
}
vec2 BRDF(float NoV, float roughness)
{
// Normal always points along z-axis for the 2D lookup
const vec3 N = vec3(0.0, 0.0, 1.0);
vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
vec2 LUT = vec2(0.0);
for(uint i = 0u; i < NUM_SAMPLES; i++) {
vec2 Xi = hammersley2d(i, NUM_SAMPLES);
vec3 H = importanceSample_GGX(Xi, roughness, N);
vec3 L = 2.0 * dot(V, H) * H - V;
float dotNL = max(dot(N, L), 0.0);
float dotNV = max(dot(N, V), 0.0);
float dotVH = max(dot(V, H), 0.0);
float dotNH = max(dot(H, N), 0.0);
if (dotNL > 0.0) {
float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
float G_Vis = (G * dotVH) / (dotNH * dotNV);
float Fc = pow(1.0 - dotVH, 5.0);
LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
}
}
return LUT / float(NUM_SAMPLES);
}
void main()
{
outColor = vec4(BRDF(vary_uv.s, 1.0-vary_uv.t), 0.0, 1.0);
}

View File

@ -0,0 +1,39 @@
/**
* @file class3\deferred\genbrdflutV.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
VARYING vec2 vary_uv;
void main()
{
//transform vertex
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_uv = position.xy*0.5+0.5;
gl_Position = vec4(position.xyz, 1.0);
}

View File

@ -92,86 +92,68 @@ vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c);
// These are in deferredUtil.glsl but we can't set: mFeatures.isDeferred to include it
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
vec3 scaleSoftClipFrag(vec3 l);
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec2 getGGX( vec2 brdfPoint );
void initMaterial( vec3 diffuse, vec3 packedORM,
out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,
vec3 pos, vec3 norm, float glossiness, float envIntensity);
void pbrDirectionalLight(inout vec3 colorDiffuse,
inout vec3 colorSpec,
vec3 sunlit,
float scol,
vec3 reflect0,
vec3 reflect90,
vec3 c_diff,
float alphaRough,
float vh,
float nl,
float nv,
float nh);
void pbrIbl(out vec3 colorDiffuse, // diffuse color output
out vec3 colorSpec, // specular color output,
// PBR interface
vec3 pbrIbl(vec3 diffuseColor,
vec3 specularColor,
vec3 radiance, // radiance map sample
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv,
float perceptualRough, // roughness factor
float gloss, // 1.0 - roughness factor
vec3 reflect0,
vec3 c_diff);
float nv, // normal dot view vector
float perceptualRoughness);
// lp = light position
// la = linear attenuation, light radius
// fa = falloff
// See: LLRender::syncLightState()
vec3 calcPointLightOrSpotLight(vec3 reflect0, vec3 reflect90, float alphaRough, vec3 c_diff,
vec3 lightColor, vec3 diffuse, vec3 p, vec3 v, vec3 n, vec4 lp, vec3 ln,
float lightSize, float lightFalloff, float is_pointlight, float ambiance)
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 p, // pixel position
vec3 v, // view vector (negative normalized pixel position)
vec3 lp, // light position
vec3 ld, // light direction (for spotlights)
vec3 lightColor,
float lightSize, float falloff, float is_pointlight, float ambiance)
{
vec3 intensity = vec3(0);
vec3 color = vec3(0,0,0);
vec3 lv = lp.xyz - p;
vec3 h, l;
float nh, nl, nv, vh, lightDist;
calcHalfVectors(lv,n,v,h,l,nh,nl,nv,vh,lightDist);
float dist = lightDist/lightSize;
float lightDist = length(lv);
if (dist <= 1.0 && nl > 0.0)
float dist = lightDist / lightSize;
if (dist <= 1.0)
{
float dist_atten = calcLegacyDistanceAttenuation(dist,lightFalloff);
lv /= lightDist;
float specWeight = 1.0;
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
lv = normalize(lv);
float spot = max(dot(-ln, lv), is_pointlight);
nl *= spot * spot;
vec3 intensity = dist_atten * lightColor * 3.0;
if (nl > 0.0)
{
vec3 color = vec3(0);
intensity = dist_atten * nl * lightColor;
color += intensity * BRDFLambertian(reflect0, reflect90, c_diff, specWeight, vh);
color += intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
return color;
}
color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
}
return intensity;
return color;
}
void main()
{
vec3 color = vec3(0,0,0);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec3 pos = vary_position;
@ -184,10 +166,11 @@ void main()
vec3 atten;
calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
// IF .mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
// vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
// else
vec4 albedo = texture2D(diffuseMap, vary_texcoord0.xy).rgba;
vec4 albedo = texture(diffuseMap, vary_texcoord0.xy).rgba;
albedo.rgb = srgb_to_linear(albedo.rgb);
#ifdef HAS_ALPHA_MASK
if (albedo.a < minimum_alpha)
@ -196,9 +179,9 @@ void main()
}
#endif
vec3 base = vertex_color.rgb * albedo.rgb;
vec3 baseColor = vertex_color.rgb * albedo.rgb;
vec3 vNt = texture2D(bumpMap, vary_texcoord1.xy).xyz*2.0-1.0;
vec3 vNt = texture(bumpMap, vary_texcoord1.xy).xyz*2.0-1.0;
float sign = vary_sign;
vec3 vN = vary_normal;
vec3 vT = vary_tangent.xyz;
@ -214,61 +197,43 @@ void main()
scol = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
#endif
// RGB = Occlusion, Roughness, Metal
// default values, see LLViewerFetchedTexture::sWhiteImagep since roughnessFactor and metallicFactor are multiplied in
// occlusion 1.0
// roughness 0.0
// metal 0.0
vec3 packedORM = texture2D(specularMap, vary_texcoord2.xy).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: lldrawpoolapha.cpp
vec3 orm = texture(specularMap, vary_texcoord2.xy).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
packedORM.g *= roughnessFactor;
packedORM.b *= metallicFactor;
float perceptualRoughness = orm.g * roughnessFactor;
float metallic = orm.b * metallicFactor;
float ao = orm.r;
// emissiveColor is the emissive color factor from GLTF and is already in linear space
vec3 colorEmissive = emissiveColor;
// emissiveMap here is a vanilla RGB texture encoded as sRGB, manually convert to linear
colorEmissive *= srgb_to_linear(texture2D(emissiveMap, vary_texcoord0.xy).rgb);
vec3 colorDiffuse = vec3(0);
vec3 colorSpec = vec3(0);
float IOR = 1.5; // default Index Of Refraction 1.5 (dielectrics)
float ao = packedORM.r;
float perceptualRough = packedORM.g;
float metal = packedORM.b;
vec3 v = -normalize(vary_position.xyz);
vec3 n = norm.xyz;
vec3 h, l;
float nh, nl, nv, vh, lightDist;
calcHalfVectors(light_dir, n, v, h, l, nh, nl, nv, vh, lightDist);
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( base, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
float gloss = 1.0 - perceptualRough;
// PBR IBL
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
vec3 legacyenv = vec3(0);
vec3 legacyenv = vec3(0);
sampleReflectionProbes(irradiance, radiance, legacyenv, pos.xyz, norm.xyz, gloss, 0.0);
irradiance = max(amblit,irradiance) * ambocc;
irradiance = max(srgb_to_linear(amblit),irradiance) * ambocc*4.0;
pbrIbl(colorDiffuse, colorSpec, radiance, irradiance, ao, nv, perceptualRough, gloss, reflect0, c_diff);
vec3 f0 = vec3(0.04);
// Sun/Moon Lighting
if (nl > 0.0 || nv > 0.0)
{
pbrDirectionalLight(colorDiffuse, colorSpec, srgb_to_linear(sunlit), scol, reflect0, reflect90, c_diff, alphaRough, vh, nl, nv, nh);
}
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 col = colorDiffuse + colorEmissive + colorSpec;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
vec3 v = -normalize(pos.xyz);
float NdotV = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0);
color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness);
color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, v, light_dir) * sunlit*8.0 * scol;
color += colorEmissive;
vec3 light = vec3(0);
// Punctual lights
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight( reflect0, reflect90, alphaRough, c_diff, light_diffuse[i].rgb, base.rgb, pos.xyz, v, n, light_position[i], light_direction[i].xyz, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w );
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
LIGHT_LOOP(1)
LIGHT_LOOP(2)
@ -278,12 +243,12 @@ void main()
LIGHT_LOOP(6)
LIGHT_LOOP(7)
col.rgb += light.rgb;
color.rgb += light.rgb;
col.rgb = linear_to_srgb(col.rgb);
col *= atten.r;
col += 2.0*additive;
col = scaleSoftClipFrag(col);
color.rgb = linear_to_srgb(color.rgb);
color *= atten.r;
color += 2.0*additive;
color = scaleSoftClipFrag(color);
frag_color = vec4(col,albedo.a * vertex_color.a);
frag_color = vec4(color,albedo.a * vertex_color.a);
}

View File

@ -38,63 +38,190 @@ uniform int sourceIdx;
VARYING vec3 vary_dir;
// =============================================================================================================
// Parts of this file are (c) 2018 Sascha Willems
// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/irradiancecube.frag
/*
MIT License
Copyright (c) 2018 Sascha Willems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// =============================================================================================================
// Code below is derived from the Khronos GLTF Sample viewer:
// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag
#define MATH_PI 3.1415926535897932384626433832795
#define PI 3.1415926535897932384626433832795
float u_roughness = 1.0;
int u_sampleCount = 16;
float u_lodBias = 2.0;
int u_width = 64;
// Hammersley Points on the Hemisphere
// CC BY 3.0 (Holger Dammertz)
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// with adapted interface
float radicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
// hammersley2d describes a sequence of points in the 2d unit square [0,1)^2
// that can be used for quasi Monte Carlo integration
vec2 hammersley2d(int i, int N) {
return vec2(float(i)/float(N), radicalInverse_VdC(uint(i)));
}
// Hemisphere Sample
// TBN generates a tangent bitangent normal coordinate frame from the normal
// (the normal must be normalized)
mat3 generateTBN(vec3 normal)
{
vec3 bitangent = vec3(0.0, 1.0, 0.0);
float NdotUp = dot(normal, vec3(0.0, 1.0, 0.0));
float epsilon = 0.0000001;
/*if (1.0 - abs(NdotUp) <= epsilon)
{
// Sampling +Y or -Y, so we need a more robust bitangent.
if (NdotUp > 0.0)
{
bitangent = vec3(0.0, 0.0, 1.0);
}
else
{
bitangent = vec3(0.0, 0.0, -1.0);
}
}*/
vec3 tangent = normalize(cross(bitangent, normal));
bitangent = cross(normal, tangent);
return mat3(tangent, bitangent, normal);
}
struct MicrofacetDistributionSample
{
float pdf;
float cosTheta;
float sinTheta;
float phi;
};
MicrofacetDistributionSample Lambertian(vec2 xi, float roughness)
{
MicrofacetDistributionSample lambertian;
// Cosine weighted hemisphere sampling
// http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#Cosine-WeightedHemisphereSampling
lambertian.cosTheta = sqrt(1.0 - xi.y);
lambertian.sinTheta = sqrt(xi.y); // equivalent to `sqrt(1.0 - cosTheta*cosTheta)`;
lambertian.phi = 2.0 * MATH_PI * xi.x;
lambertian.pdf = lambertian.cosTheta / MATH_PI; // evaluation for solid angle, therefore drop the sinTheta
return lambertian;
}
// getImportanceSample returns an importance sample direction with pdf in the .w component
vec4 getImportanceSample(int sampleIndex, vec3 N, float roughness)
{
// generate a quasi monte carlo point in the unit square [0.1)^2
vec2 xi = hammersley2d(sampleIndex, u_sampleCount);
MicrofacetDistributionSample importanceSample;
// generate the points on the hemisphere with a fitting mapping for
// the distribution (e.g. lambertian uses a cosine importance)
importanceSample = Lambertian(xi, roughness);
// transform the hemisphere sample to the normal coordinate frame
// i.e. rotate the hemisphere to the normal direction
vec3 localSpaceDirection = normalize(vec3(
importanceSample.sinTheta * cos(importanceSample.phi),
importanceSample.sinTheta * sin(importanceSample.phi),
importanceSample.cosTheta
));
mat3 TBN = generateTBN(N);
vec3 direction = TBN * localSpaceDirection;
return vec4(direction, importanceSample.pdf);
}
// Mipmap Filtered Samples (GPU Gems 3, 20.4)
// https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-20-gpu-based-importance-sampling
// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
float computeLod(float pdf)
{
// // Solid angle of current sample -- bigger for less likely samples
// float omegaS = 1.0 / (float(u_sampleCount) * pdf);
// // Solid angle of texel
// // note: the factor of 4.0 * MATH_PI
// float omegaP = 4.0 * MATH_PI / (6.0 * float(u_width) * float(u_width));
// // Mip level is determined by the ratio of our sample's solid angle to a texel's solid angle
// // note that 0.5 * log2 is equivalent to log4
// float lod = 0.5 * log2(omegaS / omegaP);
// babylon introduces a factor of K (=4) to the solid angle ratio
// this helps to avoid undersampling the environment map
// this does not appear in the original formulation by Jaroslav Krivanek and Mark Colbert
// log4(4) == 1
// lod += 1.0;
// We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps
// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
float lod = 0.5 * log2( 6.0 * float(u_width) * float(u_width) / (float(u_sampleCount) * pdf));
return lod;
}
vec3 filterColor(vec3 N)
{
//return textureLod(uCubeMap, N, 3.0).rgb;
vec3 color = vec3(0.f);
float weight = 0.0f;
for(int i = 0; i < u_sampleCount; ++i)
{
vec4 importanceSample = getImportanceSample(i, N, 1.0);
vec3 H = vec3(importanceSample.xyz);
float pdf = importanceSample.w;
// mipmap filtered samples (GPU Gems 3, 20.4)
float lod = computeLod(pdf);
// apply the bias to the lod
lod += u_lodBias;
lod = clamp(lod, 0, 7);
// sample lambertian at a lower resolution to avoid fireflies
vec3 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod).rgb;
color += lambertian;
}
if(weight != 0.0f)
{
color /= weight;
}
else
{
color /= float(u_sampleCount);
}
return color.rgb ;
}
// entry point
void main()
{
float deltaPhi = (2.0 * PI) / 11.25;
float deltaTheta = (0.5 * PI) / 4.0;
float mipLevel = 2;
vec3 color = vec3(0);
vec3 N = normalize(vary_dir);
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = normalize(cross(up, N));
up = normalize(cross(N, right));
const float TWO_PI = PI * 2.0;
const float HALF_PI = PI * 0.5;
vec3 color = vec3(0.0);
uint sampleCount = 0u;
for (float phi = 0.0; phi < TWO_PI; phi += deltaPhi) {
for (float theta = 0.0; theta < HALF_PI; theta += deltaTheta) {
vec3 tempVec = cos(phi) * right + sin(phi) * up;
vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec;
color += textureLod(reflectionProbes, vec4(sampleVector, sourceIdx), mipLevel).rgb * cos(theta) * sin(theta);
sampleCount++;
}
}
frag_color = vec4(PI * color / float(sampleCount), 1.0);
color = filterColor(vary_dir);
frag_color = vec4(color,1.0);
}
// =============================================================================================================

View File

@ -66,7 +66,7 @@ SOFTWARE.
// =============================================================================================================
uniform float roughness;
//uniform float roughness;
uniform float mipLevel;
@ -123,14 +123,18 @@ float D_GGX(float dotNH, float roughness)
return (alpha2)/(PI * denom*denom);
}
vec3 prefilterEnvMap(vec3 R, float roughness)
vec3 prefilterEnvMap(vec3 R)
{
vec3 N = R;
vec3 V = R;
vec3 color = vec3(0.0);
float totalWeight = 0.0;
float envMapDim = 256.0;
int numSamples = 32/max(int(mipLevel), 1);
int numSamples = 8;
float numMips = 7.0;
float roughness = (mipLevel+1)/numMips;
for(uint i = 0u; i < numSamples; i++) {
vec2 Xi = hammersley2d(i, numSamples);
@ -150,8 +154,9 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
// Solid angle of 1 pixel across all cube faces
float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
// Biased (+1.0) mip level for better result
//float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
color += textureLod(reflectionProbes, vec4(L,sourceIdx), mipLevel).rgb * dotNL;
//float mip = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
float mip = clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, 7.f);
color += textureLod(reflectionProbes, vec4(L,sourceIdx), mip).rgb * dotNL;
totalWeight += dotNL;
}
@ -162,7 +167,7 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
void main()
{
vec3 N = normalize(vary_dir);
frag_color = vec4(prefilterEnvMap(N, roughness), 1.0);
frag_color = vec4(prefilterEnvMap(N), 1.0);
}
// =============================================================================================================

View File

@ -39,6 +39,7 @@ VARYING vec2 vary_texcoord0;
void main()
{
#if 0
float w[9];
float c = 1.0/16.0; //corner weight
@ -72,4 +73,7 @@ void main()
//color /= wsum;
frag_color = vec4(color, 1.0);
#else
frag_color = vec4(texture2DRect(screenMap, vary_texcoord0.xy).rgb, 1.0);
#endif
}

View File

@ -52,20 +52,24 @@ uniform mat4 inv_proj;
VARYING vec4 vary_fragcoord;
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);
vec4 getPosition(vec2 pos_screen);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec2 getScreenXY(vec4 clip);
void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
vec3 srgb_to_linear(vec3 c);
// Util
vec3 hue_to_rgb(float hue);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void main()
{
#if defined(LOCAL_LIGHT_KILL)
@ -87,38 +91,43 @@ void main()
vec3 diffuse = texture2DRect(diffuseRect, tc).rgb;
vec3 h, l, v = -normalize(pos);
float nh, nl, nv, vh, lightDist;
float nh, nv, vh, lightDist;
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorDiffuse = vec3(0);
vec3 colorSpec = vec3(0);
vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
vec3 orm = texture2DRect(emissiveRect, tc).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
for (int light_idx = 0; light_idx < LIGHT_COUNT; ++light_idx)
{
vec3 lightColor = light_col[ light_idx ].rgb; // Already in linear, see pipeline.cpp: volume->getLightLinearColor();
float falloff = light_col[ light_idx ].a;
float lightSize = light [ light_idx ].w;
vec3 lv =(light [ light_idx ].xyz - pos);
calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
float lightSize = light[ light_idx ].w;
vec3 lv = light[ light_idx ].xyz - pos;
lightDist = length(lv);
float dist = lightDist / lightSize;
if (dist <= 1.0 && nl > 0.0)
if (dist <= 1.0)
{
lv /= lightDist;
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
vec3 intensity = dist_atten * nl * lightColor;
colorDiffuse += intensity * BRDFLambertian (reflect0, reflect90, c_diff , specWeight, vh);
colorSpec += intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
vec3 intensity = dist_atten * lightColor * 3.0;
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
}
}
final_color = colorDiffuse + colorSpec;
}
else
{

View File

@ -28,40 +28,6 @@
/*[EXTRA_CODE_HERE]*/
#define DEBUG_ANY_LIGHT_TYPE 0 // Output blue light cone
#define DEBUG_LEG_LIGHT_TYPE 0 // Show Legacy objects in blue
#define DEBUG_PBR_LIGHT_TYPE 0 // Ouput gray if PBR multiSpot lights object
#define DEBUG_PBR_SPOT 0
#define DEBUG_PBR_SPOT_DIFFUSE 0 // PBR diffuse lit
#define DEBUG_PBR_SPOT_SPECULAR 0 // PBR spec lit
#define DEBUG_LIGHT_FRUSTUM 0 // If projected light effects a surface
#define DEBUG_AMBIANCE_COLOR 0 // calculated ambiance color
#define DEBUG_AMBIANCE_AOE 0 // area of effect using inverse ambiance color
#define DEBUG_AMBIANCE_FINAL 0 // light color * ambiance color
#define DEBUG_NOISE 0 // monochrome noise
#define DEBUG_SHADOW 0 // Show inverted shadow
#define DEBUG_SPOT_DIFFUSE 0 // dot(n,l) * dist_atten
#define DEBUG_SPOT_NL 0 // monochome area effected by light
#define DEBUG_SPOT_SPEC_POS 0
#define DEBUG_SPOT_REFLECTION 0 // color: pos reflected along n
#define DEBUG_SPOT_ZERO 0 // Output zero for spotlight
#define DEBUG_PBR_LIGHT_H 0 // Half vector
#define DEBUG_PBR_LIHGT_L 0 // Light vector
#define DEBUG_PBR_LIGHT_NH 0 // colorized dot(n,h)
#define DEBUG_PBR_LIGHT_NL 0 // colorized dot(n,l)
#define DEBUG_PBR_LIGHT_NV 0 // colorized dot(n,v)
#define DEBUG_PBR_LIGHT_VH 0 // colorized dot(v,h)
#define DEBUG_PBR_LIGHT_DIFFUSE_COLOR 0 // non PBR spotlight
#define DEBUG_PBR_LIGHT_SPECULAR_COLOR 0 // non PBR spotlight
#define DEBUG_PBR_LIGHT_INTENSITY 0 // Light intensity
#define DEBUG_PBR_LIGHT_INTENSITY_NL 0 // Light intensity * dot(n,l)
#define DEBUG_PBR_LIGHT_BRDF_DIFFUSE 0 // like "fullbright" if no "nl" factor
#define DEBUG_PBR_LIGHT_BRDF_SPECULAR 0
#define DEBUG_PBR_LIGHT_BRDF_FINAL 0 // BRDF Diffuse + BRDF Specular
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
@ -107,19 +73,15 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec3 colorized_dot(float x);
bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
vec2 getScreenXY(vec4 clip);
void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
vec3 srgb_to_linear(vec3 cs);
vec4 texture2DLodSpecular(vec2 tc, float lod);
@ -127,6 +89,13 @@ vec4 getPosition(vec2 pos_screen);
const float M_PI = 3.14159265;
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void main()
{
#if defined(LOCAL_LIGHT_KILL)
@ -178,11 +147,17 @@ void main()
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorDiffuse = vec3(0);
vec3 colorSpec = vec3(0);
vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
float metal = packedORM.b;
vec3 orm = texture2DRect(emissiveRect, tc).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
// We need this additional test inside a light's frustum since a spotlight's ambiance can be applied
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
@ -194,111 +169,16 @@ void main()
if (nl > 0.0)
{
amb_da += (nl*0.5 + 0.5) * proj_ambiance;
lit = nl * dist_atten;
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
slit = getProjectedLightSpecularColor( pos, n );
float exposure = M_PI;
dlit *= exposure;
slit *= exposure;
colorDiffuse = shadow * lit * dlit * BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
colorSpec = shadow * lit * slit * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
colorSpec += shadow * lit * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
#if DEBUG_PBR_SPOT_DIFFUSE
colorDiffuse = dlit.rgb; colorSpec = vec3(0);
#endif
#if DEBUG_PBR_SPOT_SPECULAR
colorDiffuse = vec3(0); colorSpec = slit.rgb;
#endif
#if DEBUG_PBR_SPOT
colorDiffuse = dlit; colorSpec = vec3(0);
colorDiffuse *= nl;
colorDiffuse *= shadow;
#endif
vec3 intensity = dist_atten * dlit * 3.0 * shadow; // Legacy attenuation
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
}
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
colorDiffuse += diffuse.rgb * amb_rgb;
#if DEBUG_AMBIANCE_FINAL
colorDiffuse = diffuse.rgb * amb_rgb; colorSpec = vec3(0);
#endif
#if DEBUG_LIGHT_FRUSTUM
colorDiffuse = vec3(0,1,0); colorSpec = vec3(0);
#endif
#if DEBUG_NOISE
float noise = texture2D(noiseMap, tc/128.0).b;
colorDiffuse = vec3(noise); colorSpec = vec3(0);
#endif
final_color += diffuse.rgb * amb_rgb;
}
#if DEBUG_PBR_LIGHT_TYPE
colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_H
colorDiffuse = h*0.5 + 0.5; colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIHGT_L
colorDiffuse = l*0.5 + 0.5; colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_NH
colorDiffuse = colorized_dot(nh); colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_NL
colorDiffuse = colorized_dot(nl); colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_NV
colorDiffuse = colorized_dot(nv); colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_VH
colorDiffuse = colorized_dot(vh); colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_DIFFUSE_COLOR
colorDiffuse = dlit;
#endif
#if DEBUG_PBR_LIGHT_SPECULAR_COLOR
colorDiffuse = slit;
#endif
#if DEBUG_PBR_LIGHT_INTENSITY
colorDiffuse = getLightIntensitySpot( color, size, lightDist, v ); colorSpec = vec3(0);
// colorDiffuse = nl * dist_atten;
#endif
#if DEBUG_PBR_LIGHT_INTENSITY_NL
colorDiffuse = getLightIntensitySpot( color, size, lightDist, v ) * nl; colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_BRDF_DIFFUSE
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
colorDiffuse = BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
colorSpec = vec3(0);
#endif
#if DEBUG_PBR_LIGHT_BRDF_SPECULAR
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
colorDiffuse = vec3(0);
colorSpec = BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
#endif
#if DEBUG_PBR_LIGHT_BRDF_FINAL
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
colorDiffuse = nl * BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
colorSpec = nl * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
#endif
final_color = colorDiffuse + colorSpec;
}
else
{
@ -326,9 +206,6 @@ void main()
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, noise, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb;
#if DEBUG_LEG_LIGHT_TYPE
final_color = vec3(0,0,0.5);
#endif
}
if (spec.a > 0.0)
@ -376,59 +253,9 @@ void main()
}
}
}
#if DEBUG_SPOT_REFLECTION
final_color = ref;
#endif
}
#if DEBUG_LIGHT_FRUSTUM
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
&& proj_tc.y > 0.0 && proj_tc.y < 1.0)
{
final_color = vec3(0,0,1);
}
#endif
}
#if DEBUG_AMBIANCE_AOE
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
&& proj_tc.y > 0.0 && proj_tc.y < 1.0)
{
final_color = 1.0 - amb_rgb;
}
#endif
#if DEBUG_AMBIANCE_COLOR
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
&& proj_tc.y > 0.0 && proj_tc.y < 1.0)
{
final_color = amb_rgb;
}
#endif
#if DEBUG_SHADOW
final_color = 1.0 - vec3(shadow);
#endif
#if DEBUG_SPOT_DIFFUSE
final_color = vec3(nl * dist_atten);
#endif
#if DEBUG_SPOT_NL
final_color =vec3(nl);
#endif
#if DEBUG_SPOT_SPEC_POS
vec3 ref = reflect(normalize(pos), n);
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
final_color = pos + ref * dot(pdelta, proj_n)/ds;
#endif
#if DEBUG_SPOT_REFLECTION
final_color = reflect(normalize(pos), n);
#endif
#if DEBUG_SPOT_ZERO
final_color = vec3(0,0,0);
#endif
#if DEBUG_ANY_LIGHT_TYPE
final_color = vec3(0,0,0.3333);
#endif
//not sure why, but this line prevents MATBUG-194
final_color = max(final_color, vec3(0.0));

View File

@ -57,17 +57,20 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
uniform vec4 viewport;
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec4 getPosition(vec2 pos_screen);
vec2 getScreenXY(vec4 clip);
void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
vec3 srgb_to_linear(vec3 c);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void main()
{
vec3 final_color = vec3(0);
@ -96,25 +99,20 @@ void main()
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorDiffuse = vec3(0);
vec3 colorSpec = vec3(0);
vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
float lightSize = size;
vec3 lightColor = color; // Already in linear, see pipeline.cpp: volume->getLightLinearColor();
vec3 orm = texture2DRect(emissiveRect, tc).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
if (nl > 0.0)
{
vec3 intensity = dist_atten * nl * lightColor; // Legacy attenuation
colorDiffuse += intensity * BRDFLambertian (reflect0, reflect90, c_diff , specWeight, vh);
colorSpec += intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
}
final_color = colorDiffuse + colorSpec;
vec3 intensity = dist_atten * color * 3.0; // Legacy attenuation
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
}
else
{

View File

@ -524,14 +524,14 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l
vec3 pos, vec3 norm, float glossiness, float envIntensity)
{
// TODO - don't hard code lods
float reflection_lods = 8;
float reflection_lods = 7;
preProbeSample(pos);
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
ambenv = sampleProbeAmbient(pos, norm);
if (glossiness > 0.0)
//if (glossiness > 0.0)
{
float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod, 1.f);

View File

@ -89,34 +89,21 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
#endif
// PBR interface
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
void initMaterial( vec3 diffuse, vec3 packedORM,
out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
// perform PBR image based lighting according to GLTF spec
// all parameters are in linear space
void pbrIbl(out vec3 colorDiffuse, // diffuse color output
out vec3 colorSpec, // specular color output,
vec3 pbrIbl(vec3 diffuseColor,
vec3 specularColor,
vec3 radiance, // radiance map sample
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv,
float perceptualRough, // roughness factor
float gloss, // 1.0 - roughness factor
vec3 reflect0,
vec3 c_diff);
float nv, // normal dot view vector
float perceptualRoughness);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void pbrDirectionalLight(inout vec3 colorDiffuse,
inout vec3 colorSpec,
vec3 sunlit,
float scol,
vec3 reflect0,
vec3 reflect90,
vec3 c_diff,
float alphaRough,
float vh,
float nl,
float nv,
float nh);
void main()
{
@ -124,9 +111,6 @@ void main()
float depth = texture2DRect(depthMap, tc.xy).r;
vec4 pos = getPositionWithDepth(tc, depth);
vec4 norm = texture2DRect(normalMap, tc);
float envIntensity = norm.z;
norm.xyz = getNorm(tc);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
float light_gamma = 1.0 / 1.3;
@ -160,51 +144,39 @@ void main()
bool hasPBR = GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR);
if (hasPBR)
{
// 5.22.2. material.pbrMetallicRoughness.baseColorTexture
// The first three components (RGB) MUST be encoded with the sRGB transfer function.
//
// 5.19.7. material.emissiveTexture
// This texture contains RGB components encoded with the sRGB transfer function.
//
// 5.22.5. material.pbrMetallicRoughness.metallicRoughnessTexture
// These values MUST be encoded with a linear transfer function.
norm.xyz = getNorm(tc);
vec3 orm = texture2DRect(emissiveRect, tc).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
float perceptualRoughness = orm.g;
float metallic = orm.b;
float ao = orm.r * ambocc;
vec3 colorDiffuse = vec3(0);
vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
vec3 colorSpec = vec3(0);
vec3 colorEmissive = texture2DRect(specularRect, tc).rgb; //specularRect is sRGB sampler, result is in linear space
vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
float IOR = 1.5; // default Index Of Refraction 1.5 (dielectrics)
float ao = packedORM.r;
float metal = packedORM.b;
vec3 v = -normalize(pos.xyz);
vec3 n = norm.xyz;
vec3 h, l;
float nh, nl, nv, vh, lightDist;
calcHalfVectors(light_dir, n, v, h, l, nh, nl, nv, vh, lightDist);
float perceptualRough = packedORM.g; // NOTE: do NOT clamp here to be consistent with Blender, Blender is wrong and Substance is right
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse.rgb, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
float gloss = 1.0 - perceptualRough;
// PBR IBL
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
sampleReflectionProbes(irradiance, radiance, legacyenv, pos.xyz, norm.xyz, gloss, 0.0);
irradiance = max(amblit,irradiance) * ambocc;
irradiance = max(srgb_to_linear(amblit),irradiance) * ambocc*4.0;
pbrIbl(colorDiffuse, colorSpec, radiance, irradiance, ao, nv, perceptualRough, gloss, reflect0, c_diff);
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
// Add in sun/moon punctual light
if (nl > 0.0 || nv > 0.0)
{
pbrDirectionalLight(colorDiffuse, colorSpec, srgb_to_linear(sunlit), scol, reflect0, reflect90, c_diff, alphaRough, vh, nl, nv, nh);
}
//baseColor.rgb = vec3(0,0,0);
//colorEmissive = srgb_to_linear(norm.xyz*0.5+0.5);
color.rgb = colorDiffuse + colorEmissive + colorSpec;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
vec3 v = -normalize(pos.xyz);
float NdotV = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0);
color.rgb += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness);
color.rgb += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, v, normalize(light_dir)) * sunlit*8.0 * scol;
color.rgb += colorEmissive;
color = linear_to_srgb(color);
color *= atten.r;
@ -212,10 +184,14 @@ void main()
color = scaleSoftClipFrag(color);
color = srgb_to_linear(color);
frag_color.rgb = color.rgb; //output linear since local lights will be added to this shader's results
}
else
{
float envIntensity = norm.z;
norm.xyz = getNorm(tc);
float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
da = pow(da, light_gamma);
@ -278,5 +254,6 @@ void main()
frag_color.rgb = srgb_to_linear(color.rgb);
}
frag_color.a = bloom;
}

View File

@ -82,18 +82,14 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
vec2 getScreenXY(vec4 clip_point);
void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
vec3 srgb_to_linear(vec3 c);
vec4 texture2DLodSpecular(vec2 tc, float lod);
@ -101,6 +97,13 @@ vec4 getPosition(vec2 pos_screen);
const float M_PI = 3.14159265;
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void main()
{
#if defined(LOCAL_LIGHT_KILL)
@ -148,13 +151,20 @@ void main()
vec3 dlit = vec3(0, 0, 0);
vec3 slit = vec3(0, 0, 0);
vec3 amb_rgb = vec3(0);
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorDiffuse = vec3(0);
vec3 colorSpec = vec3(0);
vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
float metal = packedORM.b;
vec3 orm = texture2DRect(emissiveRect, tc).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
// We need this additional test inside a light's frustum since a spotlight's ambiance can be applied
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
@ -166,46 +176,16 @@ void main()
if (nl > 0.0)
{
amb_da += (nl*0.5 + 0.5) * proj_ambiance;
lit = nl * dist_atten;
vec3 c_diff, reflect0, reflect90;
float alphaRough, specWeight;
initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
slit = getProjectedLightSpecularColor( pos, n );
float exposure = M_PI;
dlit *= exposure;
slit *= exposure;
colorDiffuse = shadow * lit * dlit * BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
colorSpec = shadow * lit * slit * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
colorSpec += shadow * lit * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
#if DEBUG_PBR_SPOT_DIFFUSE
colorDiffuse = dlit.rgb; colorSpec = vec3(0);
#endif
#if DEBUG_PBR_SPOT_SPECULAR
colorDiffuse = vec3(0); colorSpec = slit.rgb;
#endif
#if DEBUG_PBR_SPOT
colorDiffuse = dlit; colorSpec = vec3(0);
colorDiffuse *= nl;
colorDiffuse *= shadow;
#endif
vec3 intensity = dist_atten * dlit * 3.0 * shadow; // Legacy attenuation
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
}
vec3 amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
colorDiffuse += diffuse.rgb * amb_rgb;
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb;
}
#if DEBUG_PBR_LIGHT_TYPE
colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0.0);
#endif
final_color = colorDiffuse + colorSpec;
}
else
{

View File

@ -4908,7 +4908,11 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
// LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; // <FS:Beq/> FIRE-31634 [OPENSIM] Better inventory validation logging
validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS)
if (!is_automatic
&& folder_type != LLFolderType::FT_SETTINGS
// FT_MATERIAL might need to be automatic like the rest of upload folders
&& folder_type != LLFolderType::FT_MATERIAL
)
{
// <FS:Beq> FIRE-31634 [OPENSIM] Better inventory validation logging
// LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << LLFolderType::lookup(folder_type) << "(" << ft << ") count " << count_under_root << LL_ENDL;

View File

@ -204,14 +204,14 @@ void LLMaterialEditor::setAlbedoUploadId(const LLUUID& id)
LLColor4 LLMaterialEditor::getAlbedoColor()
{
LLColor4 ret = LLColor4(childGetValue("albedo color"));
LLColor4 ret = linearColor4(LLColor4(childGetValue("albedo color")));
ret.mV[3] = getTransparency();
return ret;
}
void LLMaterialEditor::setAlbedoColor(const LLColor4& color)
{
childSetValue("albedo color", color.getValue());
childSetValue("albedo color", srgbColor4(color).getValue());
setTransparency(color.mV[3]);
}

View File

@ -2044,8 +2044,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
S32 tc_bytes_size = ((size_vertices * sizeof(LLVector2)) + 0xF) & ~0xF;
LLVector4a* combined_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 3 * size_vertices + tc_bytes_size);
LLVector4a* combined_normals = combined_positions + size_vertices;
LLVector4a* combined_tangents = combined_normals + size_vertices;
LLVector2* combined_tex_coords = (LLVector2*)(combined_tangents + size_vertices);
LLVector2* combined_tex_coords = (LLVector2*)(combined_normals + size_vertices);
// copy indices and vertices into new buffers
S32 combined_positions_shift = 0;
@ -2055,9 +2054,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
{
const LLVolumeFace &face = base_model->getVolumeFace(face_idx);
// ensure tangents have been generated or loaded
llassert(face.mMikktSpaceTangents);
// Vertices
S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a);
LLVector4a::memcpyNonAliased16((F32*)(combined_positions + combined_positions_shift), (F32*)face.mPositions, copy_bytes);
@ -2065,9 +2061,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
// Normals
LLVector4a::memcpyNonAliased16((F32*)(combined_normals + combined_positions_shift), (F32*)face.mNormals, copy_bytes);
// Tangents
LLVector4a::memcpyNonAliased16((F32*)(combined_tangents + combined_positions_shift), (F32*)face.mMikktSpaceTangents, copy_bytes);
// Tex coords
copy_bytes = face.mNumVertices * sizeof(LLVector2);
memcpy((void*)(combined_tex_coords + combined_positions_shift), (void*)face.mTexCoords, copy_bytes);
@ -2193,8 +2186,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 3 * size_vertices + tc_bytes_size);
LLVector4a* buffer_normals = buffer_positions + size_vertices;
LLVector4a* buffer_tangents = buffer_normals + size_vertices;
LLVector2* buffer_tex_coords = (LLVector2*)(buffer_tangents + size_vertices);
LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_vertices);
S32 buffer_idx_size = (size_indices * sizeof(U16) + 0xF) & ~0xF;
U16* buffer_indices = (U16*)ll_aligned_malloc_16(buffer_idx_size);
S32* old_to_new_positions_map = new S32[size_vertices];
@ -2287,7 +2279,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
// Copy vertice, normals, tcs
buffer_positions[buf_positions_copied] = combined_positions[idx];
buffer_normals[buf_positions_copied] = combined_normals[idx];
buffer_tangents[buf_positions_copied] = combined_tangents[idx];
buffer_tex_coords[buf_positions_copied] = combined_tex_coords[idx];
old_to_new_positions_map[idx] = buf_positions_copied;
@ -2332,7 +2323,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
LLVector4a::memcpyNonAliased16((F32*)new_face.mPositions, (F32*)buffer_positions, buf_positions_copied * sizeof(LLVector4a));
LLVector4a::memcpyNonAliased16((F32*)new_face.mNormals, (F32*)buffer_normals, buf_positions_copied * sizeof(LLVector4a));
LLVector4a::memcpyNonAliased16((F32*)new_face.mMikktSpaceTangents, (F32*)buffer_tangents, buf_positions_copied * sizeof(LLVector4a));
U32 tex_size = (buf_positions_copied * sizeof(LLVector2) + 0xF)&~0xF;
LLVector4a::memcpyNonAliased16((F32*)new_face.mTexCoords, (F32*)buffer_tex_coords, tex_size);

View File

@ -410,8 +410,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f;
//for (int i = 0; i < mMipChain.size(); ++i)
for (int i = 0; i < 1; ++i)
for (int i = 0; i < mMipChain.size(); ++i)
{
LL_PROFILE_GPU_ZONE("probe mip");
mMipChain[i].bindTarget();
@ -465,10 +464,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
if (mip >= 0)
{
LL_PROFILE_GPU_ZONE("probe mip copy");
mTexture->bind(0);
//glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res);
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
if (i == 0)
{
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
}
mTexture->unbind();
}
mMipChain[i].flush();
@ -492,8 +495,12 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
static LLStaticHashedString sMipLevel("mipLevel");
mMipChain[1].bindTarget();
U32 res = mMipChain[1].getWidth();
for (int i = 1; i < mMipChain.size(); ++i)
{
LL_PROFILE_GPU_ZONE("probe radiance gen");
for (int cf = 0; cf < 6; ++cf)
{ // for each cube face
LLCoordFrame frame;
@ -503,15 +510,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
frame.getOpenGLRotation(mat);
gGL.loadMatrix(mat);
mMipChain[i].bindTarget();
static LLStaticHashedString sRoughness("roughness");
gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
gRadianceGenProgram.uniform1f(sMipLevel, llmax((F32)(i - 1), 0.f));
if (i > 0)
{
gRadianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex);
}
// <FS:Ansariel> Remove QUADS rendering mode
//gGL.begin(gGL.QUADS);
//gGL.vertex3f(-1, -1, -1);
@ -529,12 +532,17 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.end();
// </FS:Ansariel>
gGL.flush();
S32 res = mMipChain[i].getWidth();
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
mMipChain[i].flush();
}
if (i != mMipChain.size() - 1)
{
res /= 2;
glViewport(0, 0, res, res);
}
}
gRadianceGenProgram.unbind();
//generate irradiance map
@ -542,7 +550,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
mTexture->bind(channel);
gIrradianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex);
gIrradianceGenProgram.uniform1i(sSourceIdx, targetIdx);
int start_mip = 0;
// find the mip target to start with based on irradiance map resolution
@ -554,8 +562,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
}
}
for (int i = start_mip; i < mMipChain.size(); ++i)
//for (int i = start_mip; i < mMipChain.size(); ++i)
{
int i = start_mip;
LL_PROFILE_GPU_ZONE("probe irradiance gen");
glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight());
for (int cf = 0; cf < 6; ++cf)
{ // for each cube face
LLCoordFrame frame;
@ -565,8 +576,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
frame.getOpenGLRotation(mat);
gGL.loadMatrix(mat);
mMipChain[i].bindTarget();
// <FS:Ansariel> Remove QUADS rendering mode
//gGL.begin(gGL.QUADS);
//gGL.vertex3f(-1, -1, -1);
@ -589,9 +598,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
mIrradianceMaps->bind(channel);
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
mTexture->bind(channel);
mMipChain[i].flush();
}
}
mMipChain[1].flush();
gIrradianceGenProgram.unbind();
}
}

View File

@ -2656,13 +2656,13 @@ LLTextureFetch::~LLTextureFetch()
// ~LLQueuedThread() called here
}
bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
{
LL_PROFILE_ZONE_SCOPED;
if (mDebugPause)
{
return false;
return -1;
}
if (f_type == FTT_SERVER_BAKE)
@ -2678,7 +2678,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
<< host << " != " << worker->mHost << LL_ENDL;
removeRequest(worker, true);
worker = NULL;
return false;
return -1;
}
}
@ -2731,13 +2731,13 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
{
if (worker->wasAborted())
{
return false; // need to wait for previous aborted request to complete
return -1; // need to wait for previous aborted request to complete
}
worker->lockWorkMutex(); // +Mw
if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) {
worker->unlockWorkMutex(); // -Mw
return false; // similar request has failed or is in a transitional state
return -1; // similar request has failed or is in a transitional state
}
worker->mActiveCount++;
worker->mNeedsAux = needs_aux;
@ -2772,10 +2772,10 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
worker->setCanUseHTTP(can_use_http) ;
worker->unlockWorkMutex(); // -Mw
}
LL_DEBUGS(LOG_TXT) << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type)
<< " Discard: " << desired_discard << " size " << desired_size << LL_ENDL;
return true;
return desired_discard;
}

View File

@ -77,7 +77,7 @@ public:
void shutDownImageDecodeThread();
// Threads: T* (but Tmain mostly)
bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
// Requests that a fetch operation be deleted from the queue.

View File

@ -253,6 +253,7 @@ LLGLSLShader gDeferredSkinnedFullbrightShinyProgram;
LLGLSLShader gDeferredSkinnedFullbrightProgram;
LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskProgram;
LLGLSLShader gNormalMapGenProgram;
LLGLSLShader gDeferredGenBrdfLutProgram;
// [RLVa:KB] - @setsphere
LLGLSLShader gRlvSphereProgram;
// [/RLVa:KB]
@ -1265,6 +1266,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredHighlightSpecularProgram.unload();
gNormalMapGenProgram.unload();
gDeferredGenBrdfLutProgram.unload();
for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i)
{
gDeferredMaterialProgram[i].unload();
@ -2877,6 +2880,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gNormalMapGenProgram.createShader(NULL, NULL);
}
if (success && gGLManager.mHasCubeMapArray)
{
gDeferredGenBrdfLutProgram.mName = "Brdf Gen Shader";
gDeferredGenBrdfLutProgram.mShaderFiles.clear();
gDeferredGenBrdfLutProgram.mShaderFiles.push_back(make_pair("deferred/genbrdflutV.glsl", GL_VERTEX_SHADER));
gDeferredGenBrdfLutProgram.mShaderFiles.push_back(make_pair("deferred/genbrdflutF.glsl", GL_FRAGMENT_SHADER));
gDeferredGenBrdfLutProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredGenBrdfLutProgram.createShader(NULL, NULL);
}
return success;
}

View File

@ -306,6 +306,7 @@ extern LLGLSLShader gDeferredWLMoonProgram;
extern LLGLSLShader gDeferredStarProgram;
extern LLGLSLShader gDeferredFullbrightShinyProgram;
extern LLGLSLShader gNormalMapGenProgram;
extern LLGLSLShader gDeferredGenBrdfLutProgram;
// [RLVa:KB] - @setsphere
extern LLGLSLShader gRlvSphereProgram;
// [/RLVa:KB]

View File

@ -2302,16 +2302,18 @@ bool LLViewerFetchedTexture::updateFetch()
}
// bypass texturefetch directly by pulling from LLTextureCache
bool fetch_request_created = false;
fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
S32 fetch_request_discard = -1;
fetch_request_discard = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
w, h, c, desired_discard, needsAux(), mCanUseHTTP);
if (fetch_request_created)
if (fetch_request_discard >= 0)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created");
mHasFetcher = TRUE;
mIsFetching = TRUE;
mRequestedDiscardLevel = desired_discard;
// in some cases createRequest can modify discard, as an example
// bake textures are always at discard 0
mRequestedDiscardLevel = llmin(desired_discard, fetch_request_discard);
mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
}

View File

@ -1332,6 +1332,8 @@ void LLPipeline::releaseLUTBuffers()
LLImageGL::deleteTextures(1, &mLightFunc);
mLightFunc = 0;
}
mPbrBrdfLut.release();
}
void LLPipeline::releaseShadowBuffers()
@ -1516,6 +1518,21 @@ void LLPipeline::createLUTBuffers()
delete [] ls;
}
mPbrBrdfLut.allocate(512, 512, GL_RG16F, false, false);
mPbrBrdfLut.bindTarget();
gDeferredGenBrdfLutProgram.bind();
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.vertex2f(-1, -1);
gGL.vertex2f(-1, 1);
gGL.vertex2f(1, -1);
gGL.vertex2f(1, 1);
gGL.end();
gGL.flush();
gDeferredGenBrdfLutProgram.unbind();
mPbrBrdfLut.flush();
}
}
@ -8516,6 +8533,13 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
deferred_target->bindTexture(3, channel, LLTexUnit::TFO_POINT); // frag_data[3]
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_BRDF_LUT, LLTexUnit::TT_TEXTURE);
if (channel > -1)
{
mPbrBrdfLut.bindTexture(0, channel);
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
if (channel > -1)
{
@ -8655,7 +8679,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
bindReflectionProbes(shader);
if (gAtmosphere)
{
// bind precomputed textures necessary for calculating sun and sky luminance
@ -9567,6 +9591,7 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_BRDF_LUT);
shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage());
shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);

View File

@ -703,6 +703,7 @@ public:
LLRenderTarget mHighlight;
LLRenderTarget mPhysicsDisplay;
LLRenderTarget mPbrBrdfLut;
LLCullResult mSky;
LLCullResult mReflectedObjects;