mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2024-12-01 12:09:15 +08:00
305 lines
14 KiB
C++
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
|
|
);
|