Last active
March 14, 2021 14:41
-
-
Save michidk/6c07cd38575ada149037d98989d9da37 to your computer and use it in GitHub Desktop.
SHADERRed BRDF Shader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0"?> | |
<project version="2"> | |
<pipeline> | |
<pass name="BRDF" type="shader" active="true" patchverts="1"> | |
<shader type="vs" path="shaders\vertex.vk" entry="main" /> | |
<shader type="ps" path="shaders\fragment.vk" entry="main" /> | |
<inputlayout> | |
<item value="Position" semantic="POSITION" /> | |
<item value="Normal" semantic="NORMAL" /> | |
<item value="Texcoord" semantic="TEXCOORD0" /> | |
</inputlayout> | |
<rendertexture /> | |
<items> | |
<item name="Sphere" type="geometry"> | |
<type>Sphere</type> | |
<width>1</width> | |
<height>1</height> | |
<depth>1</depth> | |
<topology>TriangleList</topology> | |
</item> | |
</items> | |
<itemvalues> | |
<value variable="u_MaterialData.color" for="Sphere"> | |
<row> | |
<value>0.876447856</value> | |
<value>0.514363229</value> | |
<value>0.514363229</value> | |
<value>0</value> | |
</row> | |
</value> | |
<value variable="u_MaterialData.metallic" for="Sphere"> | |
<row> | |
<value>0</value> | |
</row> | |
</value> | |
<value variable="u_MaterialData.roughness" for="Sphere"> | |
<row> | |
<value>0.100000001</value> | |
</row> | |
</value> | |
</itemvalues> | |
<variables> | |
<variable type="float4x4" name="u_FrameData.view_matrix" system="View" /> | |
<variable type="float4x4" name="u_FrameData.projection_matrix" system="Projection" /> | |
<variable type="float4x4" name="u_FrameData.modelMatrix" system="GeometryTransform" /> | |
<variable type="float4x4" name="u_FrameData.inverseModelMatrix" invert="true" system="GeometryTransform" /> | |
<variable type="float3" name="u_FrameData.cameraCoordinates" system="CameraPosition3" /> | |
<variable type="float4" name="u_MaterialData.color"> | |
<row> | |
<value>1</value> | |
<value>0.999989986</value> | |
<value>0.999989986</value> | |
<value>0</value> | |
</row> | |
</variable> | |
<variable type="float" name="u_MaterialData.metallic"> | |
<row> | |
<value>0</value> | |
</row> | |
</variable> | |
<variable type="float" name="u_MaterialData.roughness"> | |
<row> | |
<value>0</value> | |
</row> | |
</variable> | |
</variables> | |
<macros /> | |
</pass> | |
</pipeline> | |
<objects /> | |
<cameras /> | |
<settings> | |
<entry type="property" name="Sphere" item="pipe" /> | |
<entry type="file" name="BRDF" shader="vs" /> | |
<entry type="file" name="BRDF" shader="ps" /> | |
<entry type="pinned" name="u_MaterialData.color" owner="BRDF" /> | |
<entry type="pinned" name="u_MaterialData.metallic" owner="BRDF" /> | |
<entry type="pinned" name="u_MaterialData.roughness" owner="BRDF" /> | |
<entry type="camera" fp="false"> | |
<distance>14</distance> | |
<pitch>36</pitch> | |
<yaw>233</yaw> | |
<roll>360</roll> | |
</entry> | |
<entry type="clearcolor" r="0" g="0" b="0" a="0" /> | |
<entry type="usealpha" val="false" /> | |
</settings> | |
<plugindata /> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
layout (location = 0) in vec3 i_normal; | |
layout (location = 1) in vec4 i_worldpos; | |
layout (binding = 0) uniform FrameData | |
{ | |
mat4 view_matrix; | |
mat4 projection_matrix; | |
mat4 modelMatrix; | |
mat4 inverseModelMatrix; | |
vec3 cameraCoordinates; | |
} u_FrameData; | |
layout (binding = 1) uniform MaterialData { | |
vec4 color; | |
float metallic; | |
float roughness; | |
} u_MaterialData; | |
layout (location = 0) out vec4 o_color; | |
const float PI = 3.1415926535897932384626433832795; | |
// normal distribution function: Trowbridge-Reitz GGX | |
float distributionGGX(vec3 normal, vec3 halfVector, float roughness) { | |
float a = roughness * roughness; // rougness apparently looks more "correct", when beeing squared (according to Disney) | |
float a2 = a * a; | |
float nDotH = max(dot(normal, halfVector), 0.0); | |
float nDotH2 = nDotH * nDotH; | |
float denom = (nDotH2 * (a2 - 1.0) + 1.0); | |
denom = PI * denom * denom; | |
return a2 / denom; | |
} | |
// geometry function: Schlick-GGX | |
float geometrySchlickGGX(float vec, float roughness) { | |
float r = roughness + 1.0; | |
float k = (r * r) / 8.0; | |
float denom = vec * (1.0 - k) + k; | |
return vec / denom; | |
} | |
// approximate geometry: account for view dir and light dir: Smith's method | |
float geometrySmith(float nDotV, float nDotL, float roughness) { | |
return geometrySchlickGGX(nDotL, roughness) * geometrySchlickGGX(nDotV, roughness); | |
} | |
// Schlicks approximation | |
vec3 schlick(vec3 r0, float cosTheta) { | |
// we could use pow, but then it do all the float checks - which we don't need | |
return r0 + (1.0 - r0) * (1.0 - cosTheta) * (1.0 - cosTheta) * (1.0 - cosTheta) * (1.0 - cosTheta) * (1.0 - cosTheta); | |
} | |
vec3 computeRadiance(vec3 irradiance, vec3 lightDirection, vec3 normal, vec3 cameraDirection, vec3 surfaceColor) { | |
float metallic = u_MaterialData.metallic; | |
float roughness = u_MaterialData.roughness; | |
// utils | |
vec3 halfVector = normalize(cameraDirection + lightDirection); | |
float nDotH = max(dot(normal, halfVector), 0.0); | |
float nDotL = max(dot(normal, lightDirection), 0.0); | |
float hDotV = max(dot(halfVector, cameraDirection), 0.0); | |
float nDotV = max(dot(normal, cameraDirection), 0.0); | |
vec3 f0 = mix(vec3(0.04), surfaceColor, vec3(metallic)); // base relectivity: use 0.04 for non-metallic/dialectic materials else use the surface color | |
vec3 f = schlick(f0, hDotV); | |
float ndf = distributionGGX(normal, halfVector, roughness); | |
float geometry = geometrySmith(nDotV, nDotL, roughness); | |
// Cook-Torrance BRDF | |
vec3 numerator = ndf * geometry * f; | |
float denominator = 4.0 * nDotV * nDotL; | |
vec3 specular = numerator / max(denominator, 0.001); | |
vec3 kS = f; // energy of light that gets reflected | |
vec3 kD = vec3(1.0) - kS; // remaining light that gets refracted | |
kD *= 1.0 - metallic; // metalls don't refract, so set it to 0 if it's a metal | |
return (kD * surfaceColor / PI + specular) * irradiance * nDotL; | |
} | |
// irrandiance: light color in lx (= lm/m^2), values from https://en.wikipedia.org/wiki/Lux#Illuminance | |
vec3 directionalLight(vec3 directionToLight, vec3 irradiance, vec3 directionToCamera) { | |
return computeRadiance(vec3(10.1, 10.1, 10.1), normalize(vec3(1, 1, 0)), normalize(i_normal), directionToCamera, u_MaterialData.color.xyz); | |
} | |
// luminousFlux: light color in lm, values from https://en.wikipedia.org/wiki/Luminous_flux#Examples | |
vec3 pointLight(vec3 lightPosition, vec3 luminousFlux, vec3 directionToCamera) { | |
// light fall-off | |
vec3 directionToLight = normalize(lightPosition - i_worldpos.xyz); | |
float d = length(i_worldpos.xyz - lightPosition); | |
vec3 irradiance = luminousFlux / (4 * PI * d * d); | |
return computeRadiance(irradiance, directionToLight, normalize(i_normal), directionToCamera, u_MaterialData.color.xyz); | |
} | |
void main() { | |
vec3 radiance = vec3(0); | |
vec3 i_normal = normalize(i_normal); | |
vec3 directionToCamera = normalize(u_FrameData.cameraCoordinates - i_worldpos.xyz); | |
vec3 color = u_MaterialData.color.xyz; | |
// directional lights | |
radiance += directionalLight(vec3(0, 1, 0), vec3(10.1, 10.1, 10.1), directionToCamera); | |
// point lights | |
radiance += pointLight(vec3(0.1, -3, -3), vec3(100, 100, 100), directionToCamera); | |
radiance = radiance / (vec3(1.0) + radiance); // Reinhard tone mapping | |
o_color = vec4(radiance, 1.0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
layout (binding = 0) uniform FrameData | |
{ | |
mat4 view_matrix; | |
mat4 projection_matrix; | |
mat4 modelMatrix; | |
mat4 inverseModelMatrix; | |
vec3 cameraCoordinates; | |
} u_FrameData; | |
layout (location = 0) in vec3 i_position; | |
layout (location = 1) in vec3 i_normal; | |
layout (location = 0) out vec3 o_normal; | |
layout (location = 1) out vec4 o_worldPos; | |
void main() { | |
o_worldPos = u_FrameData.modelMatrix * vec4(i_position, 1); | |
gl_Position = u_FrameData.projection_matrix * u_FrameData.view_matrix * o_worldPos; | |
o_normal = mat3(transpose(u_FrameData.inverseModelMatrix)) * i_normal; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment