cuda-samples/Samples/5_Domain_Specific/smokeParticles/SmokeShaders.cpp
2022-01-13 11:35:24 +05:30

305 lines
14 KiB
C++

/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NVIDIA CORPORATION nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// GLSL shaders for particle rendering
#define STRINGIFY(A) #A
// particle vertex shader
const char *particleVS = STRINGIFY(
uniform float pointRadius; // point size in world space \n
uniform float pointScale; // scale to calculate size in pixels \n
uniform vec4 eyePos; \n
void main() \n
{
\n
vec4 wpos = vec4(gl_Vertex.xyz, 1.0); \n
gl_Position = gl_ModelViewProjectionMatrix *wpos; \n
// calculate window-space point size \n
vec4 eyeSpacePos = gl_ModelViewMatrix *wpos; \n
float dist = length(eyeSpacePos.xyz); \n
gl_PointSize = pointRadius * (pointScale / dist); \n
gl_TexCoord[0] = gl_MultiTexCoord0; // sprite texcoord \n
gl_TexCoord[1] = eyeSpacePos; \n
gl_FrontColor = gl_Color; \n
} \n
);
// motion blur shaders
const char *mblurVS = STRINGIFY(
uniform float timestep; \n
void main() \n
{
\n
vec3 pos = gl_Vertex.xyz; \n
vec3 vel = gl_MultiTexCoord0.xyz; \n
vec3 pos2 = (pos - vel*timestep).xyz; // previous position \n
gl_Position = gl_ModelViewMatrix * vec4(pos, 1.0); \n // eye space
gl_TexCoord[0] = gl_ModelViewMatrix * vec4(pos2, 1.0); \n
// aging \n
float lifetime = gl_MultiTexCoord0.w; \n
float age = gl_Vertex.w; \n
float phase = (lifetime > 0.0) ? (age / lifetime) : 1.0; \n // [0, 1]
gl_TexCoord[1].x = phase; \n
float fade = 1.0 - phase; \n
// float fade = 1.0; \n
// gl_FrontColor = gl_Color; \n
gl_FrontColor = vec4(gl_Color.xyz, gl_Color.w*fade); \n
} \n
);
// motion blur geometry shader
// - outputs stretched quad between previous and current positions
const char *mblurGS =
"#version 120\n"
"#extension GL_EXT_geometry_shader4 : enable\n"
STRINGIFY(
uniform float pointRadius; // point size in world space \n
void main() \n
{
\n
// aging \n
float phase = gl_TexCoordIn[0][1].x; \n
float radius = pointRadius; \n
// eye space \n
vec3 pos = gl_PositionIn[0].xyz; \n
vec3 pos2 = gl_TexCoordIn[0][0].xyz; \n
vec3 motion = pos - pos2; \n
vec3 dir = normalize(motion); \n
float len = length(motion); \n
vec3 x = dir *radius; \n
vec3 view = normalize(-pos); \n
vec3 y = normalize(cross(dir, view)) * radius; \n
float facing = dot(view, dir); \n
// check for very small motion to avoid jitter \n
float threshold = 0.01; \n
if ((len < threshold) || (facing > 0.95) || (facing < -0.95))
{
\n
pos2 = pos;
\n
x = vec3(radius, 0.0, 0.0);
\n
y = vec3(0.0, -radius, 0.0);
\n
} \n
// output quad \n
gl_FrontColor = gl_FrontColorIn[0]; \n
gl_TexCoord[0] = vec4(0, 0, 0, phase); \n
gl_TexCoord[1] = gl_PositionIn[0]; \n
gl_Position = gl_ProjectionMatrix * vec4(pos + x + y, 1); \n
EmitVertex(); \n
gl_TexCoord[0] = vec4(0, 1, 0, phase); \n
gl_TexCoord[1] = gl_PositionIn[0]; \n
gl_Position = gl_ProjectionMatrix * vec4(pos + x - y, 1); \n
EmitVertex(); \n
gl_TexCoord[0] = vec4(1, 0, 0, phase); \n
gl_TexCoord[1] = gl_PositionIn[0]; \n
gl_Position = gl_ProjectionMatrix * vec4(pos2 - x + y, 1); \n
EmitVertex(); \n
gl_TexCoord[0] = vec4(1, 1, 0, phase); \n
gl_TexCoord[1] = gl_PositionIn[0]; \n
gl_Position = gl_ProjectionMatrix * vec4(pos2 - x - y, 1); \n
EmitVertex(); \n
} \n
);
const char *simplePS = STRINGIFY(
void main() \n
{
\n
gl_FragColor = gl_Color; \n
} \n
);
// render particle without shadows
const char *particlePS = STRINGIFY(
uniform float pointRadius; \n
void main() \n
{
\n
// calculate eye-space sphere normal from texture coordinates \n
vec3 N; \n
N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0); \n
float r2 = dot(N.xy, N.xy); \n
if (r2 > 1.0) discard; // kill pixels outside circle \n
N.z = sqrt(1.0-r2); \n
// float alpha = saturate(1.0 - r2); \n
float alpha = clamp((1.0 - r2), 0.0, 1.0); \n
alpha *= gl_Color.w; \n
gl_FragColor = vec4(gl_Color.xyz * alpha, alpha); \n
} \n
);
// render particle including shadows
const char *particleShadowPS = STRINGIFY(
uniform float pointRadius; \n
uniform sampler2D shadowTex; \n
uniform sampler2D depthTex; \n
void main() \n
{
\n
// calculate eye-space sphere normal from texture coordinates \n
vec3 N; \n
N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0); \n
float r2 = dot(N.xy, N.xy); \n
if (r2 > 1.0) discard; \n // kill pixels outside circle
N.z = sqrt(1.0-r2); \n
vec4 eyeSpacePos = gl_TexCoord[1]; \n
vec4 eyeSpaceSpherePos = vec4(eyeSpacePos.xyz + N*pointRadius, 1.0); \n // point on sphere
vec4 shadowPos = gl_TextureMatrix[0] * eyeSpaceSpherePos; \n
vec3 shadow = vec3(1.0) - texture2DProj(shadowTex, shadowPos.xyw).xyz; \n
// float alpha = saturate(1.0 - r2); \n
float alpha = clamp((1.0 - r2), 0.0, 1.0); \n
alpha *= gl_Color.w; \n
gl_FragColor = vec4(gl_Color.xyz *shadow * alpha, alpha); \n // premul alpha
}
);
// render particle as lit sphere
const char *particleSpherePS = STRINGIFY(
uniform float pointRadius; \n
uniform vec3 lightDir = vec3(0.577, 0.577, 0.577); \n
void main() \n
{
\n
// calculate eye-space sphere normal from texture coordinates \n
vec3 N; \n
N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0); \n
float r2 = dot(N.xy, N.xy); \n
if (r2 > 1.0) discard; // kill pixels outside circle \n
N.z = sqrt(1.0-r2); \n
// calculate depth \n
vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space \n
vec4 clipSpacePos = gl_ProjectionMatrix *eyeSpacePos; \n
gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5; \n
float diffuse = max(0.0, dot(N, lightDir)); \n
gl_FragColor = diffuse *gl_Color; \n
} \n
);
const char *passThruVS = STRINGIFY(
void main() \n
{
\n
gl_Position = gl_Vertex; \n
gl_TexCoord[0] = gl_MultiTexCoord0; \n
gl_FrontColor = gl_Color; \n
} \n
);
const char *texture2DPS = STRINGIFY(
uniform sampler2D tex; \n
void main() \n
{
\n
gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); \n
} \n
);
// 4 tap 3x3 gaussian blur
const char *blurPS = STRINGIFY(
uniform sampler2D tex; \n
uniform vec2 texelSize; \n
uniform float blurRadius; \n
void main() \n
{
\n
vec4 c; \n
c = texture2D(tex, gl_TexCoord[0].xy + vec2(-0.5, -0.5)*texelSize*blurRadius); \n
c += texture2D(tex, gl_TexCoord[0].xy + vec2(0.5, -0.5)*texelSize*blurRadius); \n
c += texture2D(tex, gl_TexCoord[0].xy + vec2(0.5, 0.5)*texelSize*blurRadius); \n
c += texture2D(tex, gl_TexCoord[0].xy + vec2(-0.5, 0.5)*texelSize*blurRadius); \n
c *= 0.25; \n
gl_FragColor = c; \n
} \n
);
// floor shader
const char *floorVS = STRINGIFY(
varying vec4 vertexPosEye; // vertex position in eye space \n
varying vec3 normalEye; \n
void main() \n
{
\n
gl_Position = gl_ModelViewProjectionMatrix *gl_Vertex; \n
gl_TexCoord[0] = gl_MultiTexCoord0; \n
vertexPosEye = gl_ModelViewMatrix *gl_Vertex; \n
normalEye = gl_NormalMatrix *gl_Normal; \n
gl_FrontColor = gl_Color; \n
} \n
);
const char *floorPS = STRINGIFY(
uniform vec3 lightPosEye; // light position in eye space \n
uniform vec3 lightColor; \n
uniform sampler2D tex; \n
uniform sampler2D shadowTex; \n
varying vec4 vertexPosEye; // vertex position in eye space \n
varying vec3 normalEye; \n
void main() \n
{
\n
vec4 shadowPos = gl_TextureMatrix[0] * vertexPosEye; \n
vec4 colorMap = texture2D(tex, gl_TexCoord[0].xy); \n
vec3 N = normalize(normalEye); \n
vec3 L = normalize(lightPosEye - vertexPosEye.xyz); \n
float diffuse = max(0.0, dot(N, L)); \n
vec3 shadow = vec3(1.0) - texture2DProj(shadowTex, shadowPos.xyw).xyz; \n
if (shadowPos.w < 0.0) shadow = lightColor; \n // avoid back projections
gl_FragColor = vec4(gl_Color.xyz *colorMap.xyz *diffuse * shadow, 1.0); \n
} \n
);