mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-23 21:28:17 +08:00
add and update samples for CUDA 11.5
This commit is contained in:
18
Samples/smokeParticles/.vscode/c_cpp_properties.json
vendored
Normal file
18
Samples/smokeParticles/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../../Common"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/local/cuda/bin/nvcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
Samples/smokeParticles/.vscode/extensions.json
vendored
Normal file
7
Samples/smokeParticles/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
10
Samples/smokeParticles/.vscode/launch.json
vendored
Normal file
10
Samples/smokeParticles/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "CUDA C++: Launch",
|
||||
"type": "cuda-gdb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/smokeParticles"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
Samples/smokeParticles/.vscode/tasks.json
vendored
Normal file
15
Samples/smokeParticles/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "sample",
|
||||
"type": "shell",
|
||||
"command": "make dbg=1",
|
||||
"problemMatcher": ["$nvcc"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
243
Samples/smokeParticles/GLSLProgram.cpp
Normal file
243
Samples/smokeParticles/GLSLProgram.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include "GLSLProgram.h"
|
||||
|
||||
GLSLProgram::GLSLProgram(const char *vsource, const char *fsource) {
|
||||
mProg = compileProgram(vsource, 0, fsource);
|
||||
}
|
||||
|
||||
GLSLProgram::GLSLProgram(const char *vsource, const char *gsource,
|
||||
const char *fsource, GLenum gsInput, GLenum gsOutput) {
|
||||
mProg = compileProgram(vsource, gsource, fsource, gsInput, gsOutput);
|
||||
}
|
||||
|
||||
GLSLProgram::~GLSLProgram() {
|
||||
if (mProg) {
|
||||
glDeleteProgram(mProg);
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::enable() { glUseProgram(mProg); }
|
||||
|
||||
void GLSLProgram::disable() { glUseProgram(0); }
|
||||
|
||||
void GLSLProgram::setUniform1f(const char *name, float value) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glUniform1f(loc, value);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::setUniform2f(const char *name, float x, float y) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glUniform2f(loc, x, y);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::setUniform3f(const char *name, float x, float y, float z) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glUniform3f(loc, x, y, z);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::setUniform4f(const char *name, float x, float y, float z,
|
||||
float w) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glUniform4f(loc, x, y, z, w);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::setUniformMatrix4fv(const GLchar *name, GLfloat *m,
|
||||
bool transpose) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glUniformMatrix4fv(loc, 1, transpose, m);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::setUniformfv(const GLchar *name, GLfloat *v, int elementSize,
|
||||
int count) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc == -1) {
|
||||
#ifdef _DEBUG
|
||||
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
switch (elementSize) {
|
||||
case 1:
|
||||
glUniform1fv(loc, count, v);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
glUniform2fv(loc, count, v);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
glUniform3fv(loc, count, v);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
glUniform4fv(loc, count, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLProgram::bindTexture(const char *name, GLuint tex, GLenum target,
|
||||
GLint unit) {
|
||||
GLint loc = glGetUniformLocation(mProg, name);
|
||||
|
||||
if (loc >= 0) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
glBindTexture(target, tex);
|
||||
glUseProgram(mProg);
|
||||
glUniform1i(loc, unit);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
} else {
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Error binding texture '%s'\n", name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
GLuint GLSLProgram::checkCompileStatus(GLuint shader, GLint *status) {
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, status);
|
||||
|
||||
if (!(*status)) {
|
||||
char log[2048];
|
||||
int len;
|
||||
glGetShaderInfoLog(shader, 2048, (GLsizei *)&len, log);
|
||||
printf("Error: shader(%04d), Info log: %s\n", (int)shader, log);
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GLuint GLSLProgram::compileProgram(const char *vsource, const char *gsource,
|
||||
const char *fsource, GLenum gsInput,
|
||||
GLenum gsOutput) {
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
GLint compiled = 0;
|
||||
|
||||
glShaderSource(vertexShader, 1, &vsource, 0);
|
||||
glShaderSource(fragmentShader, 1, &fsource, 0);
|
||||
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
if (checkCompileStatus(vertexShader, &compiled) == 0) {
|
||||
printf("<compileProgram compilation error with vertexShader>:\n");
|
||||
printf("%s\n", vsource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
if (checkCompileStatus(fragmentShader, &compiled) == 0) {
|
||||
printf("<compileProgram compilation error with fragmentShader>:\n");
|
||||
printf("%s\n", fsource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
|
||||
if (gsource) {
|
||||
GLuint geomShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
|
||||
glShaderSource(geomShader, 1, &gsource, 0);
|
||||
glCompileShader(geomShader);
|
||||
glGetShaderiv(geomShader, GL_COMPILE_STATUS, (GLint *)&compiled);
|
||||
|
||||
if (checkCompileStatus(geomShader, &compiled) == 0) {
|
||||
printf("<compileProgram compilation error with geomShader>:\n");
|
||||
printf("%s\n", gsource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glAttachShader(program, geomShader);
|
||||
|
||||
glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT, gsInput);
|
||||
glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, gsOutput);
|
||||
glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT, 4);
|
||||
}
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
// check if program linked
|
||||
GLint success = 0;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (!success) {
|
||||
char temp[1024];
|
||||
glGetProgramInfoLog(program, 1024, 0, temp);
|
||||
fprintf(stderr, "Failed to link program:\n%s\n", temp);
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
66
Samples/smokeParticles/GLSLProgram.h
Normal file
66
Samples/smokeParticles/GLSLProgram.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
// Simple class to contain GLSL shaders/programs
|
||||
|
||||
#ifndef GLSL_PROGRAM_H
|
||||
#define GLSL_PROGRAM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class GLSLProgram {
|
||||
public:
|
||||
// construct program from strings
|
||||
GLSLProgram(const char *vsource, const char *fsource);
|
||||
GLSLProgram(const char *vsource, const char *gsource, const char *fsource,
|
||||
GLenum gsInput = GL_POINTS, GLenum gsOutput = GL_TRIANGLE_STRIP);
|
||||
~GLSLProgram();
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
void setUniform1f(const GLchar *name, GLfloat x);
|
||||
void setUniform2f(const GLchar *name, GLfloat x, GLfloat y);
|
||||
void setUniform3f(const char *name, float x, float y, float z);
|
||||
void setUniform4f(const char *name, float x, float y, float z, float w);
|
||||
void setUniformfv(const GLchar *name, GLfloat *v, int elementSize,
|
||||
int count = 1);
|
||||
void setUniformMatrix4fv(const GLchar *name, GLfloat *m, bool transpose);
|
||||
|
||||
void bindTexture(const char *name, GLuint tex, GLenum target, GLint unit);
|
||||
|
||||
inline GLuint getProgId() { return mProg; }
|
||||
|
||||
private:
|
||||
GLuint checkCompileStatus(GLuint shader, GLint *status);
|
||||
GLuint compileProgram(const char *vsource, const char *gsource,
|
||||
const char *fsource, GLenum gsInput = GL_POINTS,
|
||||
GLenum gsOutput = GL_TRIANGLE_STRIP);
|
||||
GLuint mProg;
|
||||
};
|
||||
|
||||
#endif
|
||||
294
Samples/smokeParticles/GpuArray.h
Normal file
294
Samples/smokeParticles/GpuArray.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Class to represent an array in GPU and CPU memory
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <helper_cuda.h>
|
||||
|
||||
template <class T>
|
||||
class GpuArray {
|
||||
public:
|
||||
GpuArray();
|
||||
~GpuArray();
|
||||
|
||||
enum Direction {
|
||||
HOST_TO_DEVICE,
|
||||
DEVICE_TO_HOST,
|
||||
};
|
||||
|
||||
// allocate and free
|
||||
void alloc(size_t size, bool vbo = false, bool doubleBuffer = false,
|
||||
bool useElementArray = false);
|
||||
void free();
|
||||
|
||||
// swap buffers for double buffering
|
||||
void swap();
|
||||
|
||||
// when using vbo, must map before getting device ptr
|
||||
void map();
|
||||
void unmap();
|
||||
|
||||
void copy(Direction dir, uint start = 0, uint count = 0);
|
||||
void memset(T value, uint start = 0, uint count = 0);
|
||||
|
||||
T *getDevicePtr() { return m_dptr[m_currentRead]; }
|
||||
GLuint getVbo() { return m_vbo[m_currentRead]; }
|
||||
|
||||
T *getDeviceWritePtr() { return m_dptr[m_currentWrite]; }
|
||||
GLuint getWriteVbo() { return m_vbo[m_currentWrite]; }
|
||||
|
||||
T *getHostPtr() { return m_hptr; }
|
||||
|
||||
size_t getSize() const { return m_size; }
|
||||
|
||||
private:
|
||||
GLuint createVbo(size_t size, bool useElementArray);
|
||||
|
||||
void allocDevice();
|
||||
void allocVbo(bool useElementArray);
|
||||
void allocHost();
|
||||
|
||||
void freeDevice();
|
||||
void freeVbo();
|
||||
void freeHost();
|
||||
|
||||
size_t m_size;
|
||||
T *m_dptr[2];
|
||||
GLuint m_vbo[2];
|
||||
struct cudaGraphicsResource
|
||||
*m_cuda_vbo_resource[2]; // handles OpenGL-CUDA exchange
|
||||
|
||||
T *m_hptr;
|
||||
|
||||
bool m_useVBO;
|
||||
bool m_doubleBuffer;
|
||||
uint m_currentRead, m_currentWrite;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
GpuArray<T>::GpuArray()
|
||||
: m_size(0), m_hptr(0), m_currentRead(0), m_currentWrite(0) {
|
||||
m_dptr[0] = 0;
|
||||
m_dptr[1] = 0;
|
||||
|
||||
m_vbo[0] = 0;
|
||||
m_vbo[1] = 0;
|
||||
|
||||
m_cuda_vbo_resource[0] = NULL;
|
||||
m_cuda_vbo_resource[1] = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
GpuArray<T>::~GpuArray() {
|
||||
free();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::alloc(size_t size, bool vbo, bool doubleBuffer,
|
||||
bool useElementArray) {
|
||||
m_size = size;
|
||||
|
||||
m_useVBO = vbo;
|
||||
m_doubleBuffer = doubleBuffer;
|
||||
|
||||
if (m_doubleBuffer) {
|
||||
m_currentWrite = 1;
|
||||
}
|
||||
|
||||
allocHost();
|
||||
|
||||
if (vbo) {
|
||||
allocVbo(useElementArray);
|
||||
} else {
|
||||
allocDevice();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::free() {
|
||||
freeHost();
|
||||
|
||||
if (m_vbo) {
|
||||
freeVbo();
|
||||
}
|
||||
|
||||
if (m_dptr) {
|
||||
freeDevice();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::allocHost() {
|
||||
m_hptr = (T *)new T[m_size];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::freeHost() {
|
||||
if (m_hptr) {
|
||||
delete[] m_hptr;
|
||||
m_hptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::allocDevice() {
|
||||
checkCudaErrors(cudaMalloc((void **)&m_dptr[0], m_size * sizeof(T)));
|
||||
|
||||
if (m_doubleBuffer) {
|
||||
checkCudaErrors(cudaMalloc((void **)&m_dptr[1], m_size * sizeof(T)));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::freeDevice() {
|
||||
if (m_dptr[0]) {
|
||||
checkCudaErrors(cudaFree(m_dptr[0]));
|
||||
m_dptr[0] = 0;
|
||||
}
|
||||
|
||||
if (m_dptr[1]) {
|
||||
checkCudaErrors(cudaFree(m_dptr[1]));
|
||||
m_dptr[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
GLuint GpuArray<T>::createVbo(size_t size, bool useElementArray) {
|
||||
GLuint vbo;
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
if (useElementArray) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
return vbo;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::allocVbo(bool useElementArray) {
|
||||
m_vbo[0] = createVbo(m_size * sizeof(T), useElementArray);
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
|
||||
&m_cuda_vbo_resource[0], m_vbo[0], cudaGraphicsMapFlagsWriteDiscard));
|
||||
|
||||
if (m_doubleBuffer) {
|
||||
m_vbo[1] = createVbo(m_size * sizeof(T), useElementArray);
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
|
||||
&m_cuda_vbo_resource[1], m_vbo[1], cudaGraphicsMapFlagsWriteDiscard));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::freeVbo() {
|
||||
if (m_vbo[0]) {
|
||||
checkCudaErrors(cudaGraphicsUnregisterResource(m_cuda_vbo_resource[0]));
|
||||
glDeleteBuffers(1, &m_vbo[0]);
|
||||
m_vbo[0] = 0;
|
||||
}
|
||||
|
||||
if (m_vbo[1]) {
|
||||
checkCudaErrors(cudaGraphicsUnregisterResource(m_cuda_vbo_resource[1]));
|
||||
glDeleteBuffers(1, &m_vbo[1]);
|
||||
m_vbo[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::swap() {
|
||||
std::swap(m_currentRead, m_currentWrite);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::map() {
|
||||
if (m_vbo[0]) {
|
||||
checkCudaErrors(cudaGraphicsMapResources(1, &m_cuda_vbo_resource[0], 0));
|
||||
size_t num_bytes;
|
||||
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
|
||||
(void **)&m_dptr[0], &num_bytes, m_cuda_vbo_resource[0]));
|
||||
}
|
||||
|
||||
if (m_doubleBuffer && m_vbo[1]) {
|
||||
checkCudaErrors(cudaGraphicsMapResources(1, &m_cuda_vbo_resource[1], 0));
|
||||
size_t num_bytes;
|
||||
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
|
||||
(void **)&m_dptr[1], &num_bytes, m_cuda_vbo_resource[1]));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::unmap() {
|
||||
if (m_vbo[0]) {
|
||||
checkCudaErrors(cudaGraphicsUnmapResources(1, &m_cuda_vbo_resource[0], 0));
|
||||
m_dptr[0] = 0;
|
||||
}
|
||||
|
||||
if (m_doubleBuffer && m_vbo[1]) {
|
||||
checkCudaErrors(cudaGraphicsUnmapResources(1, &m_cuda_vbo_resource[1], 0));
|
||||
m_dptr[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::copy(Direction dir, uint start, uint count) {
|
||||
if (count == 0) {
|
||||
count = (uint)m_size;
|
||||
}
|
||||
|
||||
map();
|
||||
|
||||
switch (dir) {
|
||||
case HOST_TO_DEVICE:
|
||||
checkCudaErrors(cudaMemcpy((void *)(m_dptr[m_currentRead] + start),
|
||||
(void *)(m_hptr + start), count * sizeof(T),
|
||||
cudaMemcpyHostToDevice));
|
||||
break;
|
||||
|
||||
case DEVICE_TO_HOST:
|
||||
checkCudaErrors(cudaMemcpy((void *)(m_hptr + start),
|
||||
(void *)(m_dptr[m_currentRead] + start),
|
||||
count * sizeof(T), cudaMemcpyDeviceToHost));
|
||||
break;
|
||||
}
|
||||
|
||||
unmap();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void GpuArray<T>::memset(T value, uint start, uint count) {}
|
||||
403
Samples/smokeParticles/Makefile
Normal file
403
Samples/smokeParticles/Makefile
Normal file
@@ -0,0 +1,403 @@
|
||||
################################################################################
|
||||
# Copyright (c) 2019, 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.
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# Makefile project only supported on Mac OS X and Linux Platforms)
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Location of the CUDA Toolkit
|
||||
CUDA_PATH ?= /usr/local/cuda
|
||||
|
||||
##############################
|
||||
# start deprecated interface #
|
||||
##############################
|
||||
ifeq ($(x86_64),1)
|
||||
$(info WARNING - x86_64 variable has been deprecated)
|
||||
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
|
||||
TARGET_ARCH ?= x86_64
|
||||
endif
|
||||
ifeq ($(ARMv7),1)
|
||||
$(info WARNING - ARMv7 variable has been deprecated)
|
||||
$(info WARNING - please use TARGET_ARCH=armv7l instead)
|
||||
TARGET_ARCH ?= armv7l
|
||||
endif
|
||||
ifeq ($(aarch64),1)
|
||||
$(info WARNING - aarch64 variable has been deprecated)
|
||||
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
|
||||
TARGET_ARCH ?= aarch64
|
||||
endif
|
||||
ifeq ($(ppc64le),1)
|
||||
$(info WARNING - ppc64le variable has been deprecated)
|
||||
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
|
||||
TARGET_ARCH ?= ppc64le
|
||||
endif
|
||||
ifneq ($(GCC),)
|
||||
$(info WARNING - GCC variable has been deprecated)
|
||||
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
|
||||
HOST_COMPILER ?= $(GCC)
|
||||
endif
|
||||
ifneq ($(abi),)
|
||||
$(error ERROR - abi variable has been removed)
|
||||
endif
|
||||
############################
|
||||
# end deprecated interface #
|
||||
############################
|
||||
|
||||
# architecture
|
||||
HOST_ARCH := $(shell uname -m)
|
||||
TARGET_ARCH ?= $(HOST_ARCH)
|
||||
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
|
||||
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
|
||||
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
|
||||
TARGET_SIZE := 64
|
||||
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
|
||||
TARGET_SIZE := 32
|
||||
endif
|
||||
else
|
||||
TARGET_SIZE := $(shell getconf LONG_BIT)
|
||||
endif
|
||||
else
|
||||
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
|
||||
endif
|
||||
|
||||
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
|
||||
ifeq ($(HOST_ARCH),aarch64)
|
||||
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
|
||||
HOST_ARCH := sbsa
|
||||
TARGET_ARCH := sbsa
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
|
||||
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
|
||||
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
|
||||
endif
|
||||
endif
|
||||
|
||||
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
|
||||
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
|
||||
TARGET_ARCH = armv7l
|
||||
endif
|
||||
|
||||
# operating system
|
||||
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
|
||||
TARGET_OS ?= $(HOST_OS)
|
||||
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
|
||||
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
|
||||
endif
|
||||
|
||||
# host compiler
|
||||
ifeq ($(TARGET_OS),darwin)
|
||||
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
|
||||
HOST_COMPILER ?= clang++
|
||||
endif
|
||||
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
|
||||
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
|
||||
ifeq ($(TARGET_OS),linux)
|
||||
HOST_COMPILER ?= arm-linux-gnueabihf-g++
|
||||
else ifeq ($(TARGET_OS),qnx)
|
||||
ifeq ($(QNX_HOST),)
|
||||
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
|
||||
endif
|
||||
ifeq ($(QNX_TARGET),)
|
||||
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
|
||||
endif
|
||||
export QNX_HOST
|
||||
export QNX_TARGET
|
||||
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
|
||||
else ifeq ($(TARGET_OS),android)
|
||||
HOST_COMPILER ?= arm-linux-androideabi-g++
|
||||
endif
|
||||
else ifeq ($(TARGET_ARCH),aarch64)
|
||||
ifeq ($(TARGET_OS), linux)
|
||||
HOST_COMPILER ?= aarch64-linux-gnu-g++
|
||||
else ifeq ($(TARGET_OS),qnx)
|
||||
ifeq ($(QNX_HOST),)
|
||||
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
|
||||
endif
|
||||
ifeq ($(QNX_TARGET),)
|
||||
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
|
||||
endif
|
||||
export QNX_HOST
|
||||
export QNX_TARGET
|
||||
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
|
||||
else ifeq ($(TARGET_OS), android)
|
||||
HOST_COMPILER ?= aarch64-linux-android-clang++
|
||||
endif
|
||||
else ifeq ($(TARGET_ARCH),sbsa)
|
||||
HOST_COMPILER ?= aarch64-linux-gnu-g++
|
||||
else ifeq ($(TARGET_ARCH),ppc64le)
|
||||
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
|
||||
endif
|
||||
endif
|
||||
HOST_COMPILER ?= g++
|
||||
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
|
||||
|
||||
# internal flags
|
||||
NVCCFLAGS := -m${TARGET_SIZE}
|
||||
CCFLAGS :=
|
||||
LDFLAGS :=
|
||||
|
||||
# build flags
|
||||
ifeq ($(TARGET_OS),darwin)
|
||||
LDFLAGS += -rpath $(CUDA_PATH)/lib
|
||||
CCFLAGS += -arch $(HOST_ARCH)
|
||||
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
|
||||
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
|
||||
CCFLAGS += -mfloat-abi=hard
|
||||
else ifeq ($(TARGET_OS),android)
|
||||
LDFLAGS += -pie
|
||||
CCFLAGS += -fpie -fpic -fexceptions
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
|
||||
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
|
||||
ifneq ($(TARGET_FS),)
|
||||
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
|
||||
ifeq ($(GCCVERSIONLTEQ46),1)
|
||||
CCFLAGS += --sysroot=$(TARGET_FS)
|
||||
endif
|
||||
LDFLAGS += --sysroot=$(TARGET_FS)
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
|
||||
ifneq ($(TARGET_FS),)
|
||||
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
|
||||
ifeq ($(GCCVERSIONLTEQ46),1)
|
||||
CCFLAGS += --sysroot=$(TARGET_FS)
|
||||
endif
|
||||
LDFLAGS += --sysroot=$(TARGET_FS)
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
|
||||
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
|
||||
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
|
||||
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
|
||||
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
|
||||
NVCCFLAGS += --qpp-config 5.4.0,gcc_ntoaarch64le
|
||||
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
|
||||
LDFLAGS += -lsocket
|
||||
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
|
||||
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
|
||||
ifdef TARGET_OVERRIDE
|
||||
LDFLAGS += -lslog2
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_FS),)
|
||||
LDFLAGS += -L$(TARGET_FS)/usr/lib
|
||||
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
|
||||
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
|
||||
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
|
||||
CCFLAGS += -I$(TARGET_FS)/../include
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef TARGET_OVERRIDE # cuda toolkit targets override
|
||||
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
|
||||
endif
|
||||
|
||||
# Install directory of different arch
|
||||
CUDA_INSTALL_TARGET_DIR :=
|
||||
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
|
||||
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
|
||||
else ifeq ($(TARGET_ARCH),ppc64le)
|
||||
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
|
||||
endif
|
||||
|
||||
# Debug build flags
|
||||
ifeq ($(dbg),1)
|
||||
NVCCFLAGS += -g -G
|
||||
BUILD_TYPE := debug
|
||||
else
|
||||
BUILD_TYPE := release
|
||||
endif
|
||||
|
||||
ALL_CCFLAGS :=
|
||||
ALL_CCFLAGS += $(NVCCFLAGS)
|
||||
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
|
||||
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
|
||||
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
|
||||
|
||||
SAMPLE_ENABLED := 1
|
||||
|
||||
# This sample is not supported on QNX
|
||||
ifeq ($(TARGET_OS),qnx)
|
||||
$(info >>> WARNING - smokeParticles is not supported on QNX - waiving sample <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
|
||||
ALL_LDFLAGS :=
|
||||
ALL_LDFLAGS += $(ALL_CCFLAGS)
|
||||
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
|
||||
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
|
||||
|
||||
# Common includes and paths for CUDA
|
||||
INCLUDES := -I../../Common
|
||||
LIBRARIES :=
|
||||
|
||||
################################################################################
|
||||
|
||||
# Makefile include to help find GL Libraries
|
||||
include ./findgllib.mk
|
||||
|
||||
# OpenGL specific libraries
|
||||
ifeq ($(TARGET_OS),darwin)
|
||||
# Mac OSX specific libraries and paths to include
|
||||
LIBRARIES += -L/System/Library/Frameworks/OpenGL.framework/Libraries
|
||||
LIBRARIES += -lGL -lGLU
|
||||
ALL_LDFLAGS += -Xlinker -framework -Xlinker GLUT
|
||||
else
|
||||
LIBRARIES += $(GLLINK)
|
||||
LIBRARIES += -lGL -lGLU -lglut
|
||||
endif
|
||||
|
||||
#Detect if installed version of GCC supports required C++11
|
||||
ifeq ($(TARGET_OS),linux)
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
GCCVERSIONSTRING := $(shell expr `$(HOST_COMPILER) -dumpversion`)
|
||||
#Create version number without "."
|
||||
GCCVERSION := $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f1 -d.)
|
||||
GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f2 -d.)
|
||||
GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f3 -d.)
|
||||
# Make sure the version number has at least 3 decimals
|
||||
GCCVERSION += 00
|
||||
# Remove spaces from the version number
|
||||
GCCVERSION := $(subst $(space),$(empty),$(GCCVERSION))
|
||||
#$(warning $(GCCVERSION))
|
||||
|
||||
IS_MIN_VERSION := $(shell expr `echo $(GCCVERSION)` \>= 51000)
|
||||
|
||||
ifeq ($(IS_MIN_VERSION), 1)
|
||||
$(info >>> GCC Version is greater or equal to 5.1.0 <<<)
|
||||
else
|
||||
$(info >>> Waiving build. Minimum GCC version required is 5.1.0<<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
# Gencode arguments
|
||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64))
|
||||
SMS ?= 35 37 50 52 60 61 70 72 75 80 86
|
||||
else
|
||||
SMS ?= 35 37 50 52 60 61 70 75 80 86
|
||||
endif
|
||||
|
||||
ifeq ($(SMS),)
|
||||
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
|
||||
ifeq ($(GENCODE_FLAGS),)
|
||||
# Generate SASS code for each SM architecture listed in $(SMS)
|
||||
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
|
||||
|
||||
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
|
||||
HIGHEST_SM := $(lastword $(sort $(SMS)))
|
||||
ifneq ($(HIGHEST_SM),)
|
||||
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
|
||||
endif
|
||||
endif
|
||||
|
||||
ALL_CCFLAGS += --std=c++14 --threads 0
|
||||
|
||||
ifeq ($(SAMPLE_ENABLED),0)
|
||||
EXEC ?= @echo "[@]"
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
# Target rules
|
||||
all: build
|
||||
|
||||
build: smokeParticles
|
||||
|
||||
check.deps:
|
||||
ifeq ($(SAMPLE_ENABLED),0)
|
||||
@echo "Sample will be waived due to the above missing dependencies"
|
||||
else
|
||||
@echo "Sample is ready - all dependencies have been met"
|
||||
endif
|
||||
|
||||
GLSLProgram.o:GLSLProgram.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
ParticleSystem.o:ParticleSystem.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
ParticleSystem_cuda.o:ParticleSystem_cuda.cu
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
SmokeRenderer.o:SmokeRenderer.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
SmokeShaders.o:SmokeShaders.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
framebufferObject.o:framebufferObject.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
particleDemo.o:particleDemo.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
renderbuffer.o:renderbuffer.cpp
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
smokeParticles: GLSLProgram.o ParticleSystem.o ParticleSystem_cuda.o SmokeRenderer.o SmokeShaders.o framebufferObject.o particleDemo.o renderbuffer.o
|
||||
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
|
||||
$(EXEC) mkdir -p ../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
|
||||
$(EXEC) cp $@ ../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
|
||||
|
||||
run: build
|
||||
$(EXEC) ./smokeParticles
|
||||
|
||||
clean:
|
||||
rm -f smokeParticles GLSLProgram.o ParticleSystem.o ParticleSystem_cuda.o SmokeRenderer.o SmokeShaders.o framebufferObject.o particleDemo.o renderbuffer.o
|
||||
rm -rf ../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/smokeParticles
|
||||
|
||||
clobber: clean
|
||||
104
Samples/smokeParticles/NsightEclipse.xml
Normal file
104
Samples/smokeParticles/NsightEclipse.xml
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
|
||||
<entry>
|
||||
<name>smokeParticles</name>
|
||||
<cflags>
|
||||
<flag>--std=c++14</flag>
|
||||
</cflags>
|
||||
<cuda_api_list>
|
||||
<toolkit>cudaGraphicsMapResources</toolkit>
|
||||
<toolkit>cudaGraphicsUnmapResources</toolkit>
|
||||
<toolkit>cudaGraphicsResourceGetMappedPointer</toolkit>
|
||||
<toolkit>cudaGraphicsRegisterResource</toolkit>
|
||||
<toolkit>cudaGraphicsGLRegisterBuffer</toolkit>
|
||||
<toolkit>cudaGraphicsUnregisterResource</toolkit>
|
||||
</cuda_api_list>
|
||||
<description><![CDATA[Smoke simulation with volumetric shadows using half-angle slicing technique. Uses CUDA for procedural simulation, Thrust Library for sorting algorithms, and OpenGL for graphics rendering.]]></description>
|
||||
<devicecompilation>whole</devicecompilation>
|
||||
<files>
|
||||
<file>..\..\doc\Thrust_license.txt</file>
|
||||
<file>data\floortile.ppm</file>
|
||||
<file>data\smokeParticles_ref.ppm</file>
|
||||
<file>data\ref_smokePart_pos.bin</file>
|
||||
<file>data\ref_smokePart_vel.bin</file>
|
||||
</files>
|
||||
<includepaths>
|
||||
<path>./</path>
|
||||
<path>../</path>
|
||||
<path>../../Common</path>
|
||||
</includepaths>
|
||||
<keyconcepts>
|
||||
<concept level="advanced">Graphics Interop</concept>
|
||||
<concept level="advanced">Data Parallel Algorithms</concept>
|
||||
<concept level="advanced">Physically-Based Simulation</concept>
|
||||
</keyconcepts>
|
||||
<keywords>
|
||||
<keyword>CUDA</keyword>
|
||||
<keyword>GPGPU</keyword>
|
||||
<keyword>simulation</keyword>
|
||||
<keyword>particles</keyword>
|
||||
<keyword>OpenGL</keyword>
|
||||
<keyword>openGL</keyword>
|
||||
<keyword>CPP14</keyword>
|
||||
</keywords>
|
||||
<libraries>
|
||||
<library>GLU</library>
|
||||
<library>GL</library>
|
||||
<library framework="true" os="macosx">GLUT</library>
|
||||
<library os="linux">GLEW</library>
|
||||
<library os="linux">glut</library>
|
||||
<library os="linux">X11</library>
|
||||
</libraries>
|
||||
<librarypaths>
|
||||
<path arch="x86_64" os="linux">../../common/lib/linux/x86_64</path>
|
||||
<path arch="armv7l" os="linux">../../common/lib/linux/armv7l</path>
|
||||
<path os="macosx">../../common/lib/darwin</path>
|
||||
</librarypaths>
|
||||
<nsight_eclipse>true</nsight_eclipse>
|
||||
<primary_file>particleDemo.cpp</primary_file>
|
||||
<qatests>
|
||||
<qatest>-qatest</qatest>
|
||||
</qatests>
|
||||
<required_dependencies>
|
||||
<dependency>X11</dependency>
|
||||
<dependency>GL</dependency>
|
||||
</required_dependencies>
|
||||
<scopes>
|
||||
<scope>2:Graphics Interop</scope>
|
||||
<scope>2:Texture</scope>
|
||||
<scope>3:Physically-Based Simulation</scope>
|
||||
</scopes>
|
||||
<sm-arch>sm35</sm-arch>
|
||||
<sm-arch>sm37</sm-arch>
|
||||
<sm-arch>sm50</sm-arch>
|
||||
<sm-arch>sm52</sm-arch>
|
||||
<sm-arch>sm60</sm-arch>
|
||||
<sm-arch>sm61</sm-arch>
|
||||
<sm-arch>sm70</sm-arch>
|
||||
<sm-arch>sm72</sm-arch>
|
||||
<sm-arch>sm75</sm-arch>
|
||||
<sm-arch>sm80</sm-arch>
|
||||
<sm-arch>sm86</sm-arch>
|
||||
<supported_envs>
|
||||
<env>
|
||||
<arch>x86_64</arch>
|
||||
<platform>linux</platform>
|
||||
</env>
|
||||
<env>
|
||||
<platform>windows7</platform>
|
||||
</env>
|
||||
<env>
|
||||
<arch>x86_64</arch>
|
||||
<platform>macosx</platform>
|
||||
</env>
|
||||
<env>
|
||||
<arch>arm</arch>
|
||||
</env>
|
||||
</supported_envs>
|
||||
<supported_sm_architectures>
|
||||
<include>all</include>
|
||||
</supported_sm_architectures>
|
||||
<title>Smoke Particles</title>
|
||||
<type>exe</type>
|
||||
<whitepaper>doc\smokeParticles.pdf</whitepaper>
|
||||
</entry>
|
||||
368
Samples/smokeParticles/ParticleSystem.cpp
Normal file
368
Samples/smokeParticles/ParticleSystem.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include <helper_functions.h>
|
||||
#include <helper_cuda.h>
|
||||
|
||||
#include "ParticleSystem.h"
|
||||
#include "ParticleSystem.cuh"
|
||||
#include "particles_kernel.cuh"
|
||||
|
||||
#ifndef CUDART_PI_F
|
||||
#define CUDART_PI_F 3.141592654f
|
||||
#endif
|
||||
|
||||
/*
|
||||
This handles the particle simulation using CUDA
|
||||
*/
|
||||
|
||||
ParticleSystem::ParticleSystem(uint numParticles, bool bUseVBO, bool bUseGL)
|
||||
: m_bInitialized(false),
|
||||
m_bUseVBO(bUseVBO),
|
||||
m_numParticles(numParticles),
|
||||
m_particleRadius(0.1f),
|
||||
m_doDepthSort(false),
|
||||
m_timer(NULL),
|
||||
m_time(0.0f) {
|
||||
m_params.gravity = make_float3(0.0f, 0.0f, 0.0f);
|
||||
m_params.globalDamping = 1.0f;
|
||||
m_params.noiseSpeed = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
_initialize(numParticles, bUseGL);
|
||||
}
|
||||
|
||||
ParticleSystem::~ParticleSystem() {
|
||||
_free();
|
||||
m_numParticles = 0;
|
||||
}
|
||||
|
||||
void ParticleSystem::_initialize(int numParticles, bool bUseGL) {
|
||||
assert(!m_bInitialized);
|
||||
|
||||
createNoiseTexture(64, 64, 64);
|
||||
|
||||
m_numParticles = numParticles;
|
||||
|
||||
// allocate GPU arrays
|
||||
m_pos.alloc(m_numParticles, m_bUseVBO, true); // create as VBO
|
||||
m_vel.alloc(m_numParticles, m_bUseVBO, true);
|
||||
|
||||
m_sortKeys.alloc(m_numParticles);
|
||||
m_indices.alloc(m_numParticles, m_bUseVBO, false,
|
||||
true); // create as index buffer
|
||||
|
||||
sdkCreateTimer(&m_timer);
|
||||
setParameters(&m_params);
|
||||
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
void ParticleSystem::_free() { assert(m_bInitialized); }
|
||||
|
||||
// step the simulation
|
||||
void ParticleSystem::step(float deltaTime) {
|
||||
assert(m_bInitialized);
|
||||
|
||||
m_params.time = m_time;
|
||||
setParameters(&m_params);
|
||||
|
||||
m_pos.map();
|
||||
m_vel.map();
|
||||
|
||||
// integrate particles
|
||||
integrateSystem(m_pos.getDevicePtr(), m_pos.getDeviceWritePtr(),
|
||||
m_vel.getDevicePtr(), m_vel.getDeviceWritePtr(), deltaTime,
|
||||
m_numParticles);
|
||||
|
||||
m_pos.unmap();
|
||||
m_vel.unmap();
|
||||
|
||||
m_pos.swap();
|
||||
m_vel.swap();
|
||||
|
||||
m_time += deltaTime;
|
||||
}
|
||||
|
||||
// depth sort the particles
|
||||
void ParticleSystem::depthSort() {
|
||||
if (!m_doDepthSort) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_pos.map();
|
||||
m_indices.map();
|
||||
|
||||
// calculate depth
|
||||
calcDepth(m_pos.getDevicePtr(), m_sortKeys.getDevicePtr(),
|
||||
m_indices.getDevicePtr(), m_sortVector, m_numParticles);
|
||||
|
||||
// radix sort
|
||||
sortParticles(m_sortKeys.getDevicePtr(), m_indices.getDevicePtr(),
|
||||
m_numParticles);
|
||||
|
||||
m_pos.unmap();
|
||||
m_indices.unmap();
|
||||
}
|
||||
|
||||
uint *ParticleSystem::getSortedIndices() {
|
||||
// copy sorted indices back to CPU
|
||||
m_indices.copy(GpuArray<uint>::DEVICE_TO_HOST);
|
||||
return m_indices.getHostPtr();
|
||||
}
|
||||
|
||||
// random float [0, 1]
|
||||
inline float frand() { return rand() / (float)RAND_MAX; }
|
||||
|
||||
// signed random float [-1, 1]
|
||||
inline float sfrand() { return frand() * 2.0f - 1.0f; }
|
||||
|
||||
// random signed vector
|
||||
inline vec3f svrand() { return vec3f(sfrand(), sfrand(), sfrand()); }
|
||||
|
||||
// random point in circle
|
||||
inline vec2f randCircle() {
|
||||
vec2f r;
|
||||
|
||||
do {
|
||||
r = vec2f(sfrand(), sfrand());
|
||||
} while (length(r) > 1.0f);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// random point in sphere
|
||||
inline vec3f randSphere() {
|
||||
vec3f r;
|
||||
|
||||
do {
|
||||
r = svrand();
|
||||
} while (length(r) > 1.0f);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// initialize in regular grid
|
||||
void ParticleSystem::initGrid(vec3f start, uint3 size, vec3f spacing,
|
||||
float jitter, vec3f vel, uint numParticles,
|
||||
float lifetime) {
|
||||
srand(1973);
|
||||
|
||||
float4 *posPtr = m_pos.getHostPtr();
|
||||
float4 *velPtr = m_vel.getHostPtr();
|
||||
|
||||
for (uint z = 0; z < size.z; z++) {
|
||||
for (uint y = 0; y < size.y; y++) {
|
||||
for (uint x = 0; x < size.x; x++) {
|
||||
uint i = (z * size.y * size.x) + (y * size.x) + x;
|
||||
|
||||
if (i < numParticles) {
|
||||
vec3f pos = start + spacing * vec3f((float)x, (float)y, (float)z) +
|
||||
svrand() * jitter;
|
||||
|
||||
posPtr[i] = make_float4(pos.x, pos.y, pos.z, 0.0f);
|
||||
velPtr[i] = make_float4(vel.x, vel.y, vel.z, lifetime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize in random positions within cube
|
||||
void ParticleSystem::initCubeRandom(vec3f origin, vec3f size, vec3f vel,
|
||||
float lifetime) {
|
||||
float4 *posPtr = m_pos.getHostPtr();
|
||||
float4 *velPtr = m_vel.getHostPtr();
|
||||
|
||||
for (uint i = 0; i < m_numParticles; i++) {
|
||||
vec3f pos = origin + svrand() * size;
|
||||
posPtr[i] = make_float4(pos.x, pos.y, pos.z, 0.0f);
|
||||
velPtr[i] = make_float4(vel.x, vel.y, vel.z, lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
// add sphere on regular grid
|
||||
void ParticleSystem::addSphere(uint &index, vec3f pos, vec3f vel, int r,
|
||||
float spacing, float jitter, float lifetime) {
|
||||
float4 *posPtr = m_pos.getHostPtr();
|
||||
float4 *velPtr = m_vel.getHostPtr();
|
||||
|
||||
uint start = index;
|
||||
uint count = 0;
|
||||
|
||||
for (int z = -r; z <= r; z++) {
|
||||
for (int y = -r; y <= r; y++) {
|
||||
for (int x = -r; x <= r; x++) {
|
||||
vec3f delta = vec3f((float)x, (float)y, (float)z) * spacing;
|
||||
float dist = length(delta);
|
||||
|
||||
if ((dist <= spacing * r) && (index < m_numParticles)) {
|
||||
// vec3f p = pos + delta + svrand()*jitter;
|
||||
|
||||
posPtr[index] = make_float4(pos.x, pos.y, pos.z, 0.0f);
|
||||
velPtr[index] = make_float4(vel.x, vel.y, vel.z, lifetime);
|
||||
|
||||
index++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pos.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
m_vel.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
}
|
||||
|
||||
void ParticleSystem::reset(ParticleConfig config) {
|
||||
switch (config) {
|
||||
default:
|
||||
case CONFIG_RANDOM:
|
||||
initCubeRandom(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 1.0, 1.0), vec3f(0.0f),
|
||||
100.0);
|
||||
break;
|
||||
|
||||
case CONFIG_GRID: {
|
||||
float jitter = m_particleRadius * 0.01f;
|
||||
uint s = (int)ceilf(powf((float)m_numParticles, 1.0f / 3.0f));
|
||||
uint gridSize[3];
|
||||
gridSize[0] = gridSize[1] = gridSize[2] = s;
|
||||
initGrid(vec3f(-1.0, 0.0, -1.0), make_uint3(s, s, s),
|
||||
vec3f(m_particleRadius * 2.0f), jitter, vec3f(0.0),
|
||||
m_numParticles, 100.0);
|
||||
} break;
|
||||
}
|
||||
|
||||
m_pos.copy(GpuArray<float4>::HOST_TO_DEVICE);
|
||||
m_vel.copy(GpuArray<float4>::HOST_TO_DEVICE);
|
||||
}
|
||||
|
||||
// particle emitters
|
||||
void ParticleSystem::discEmitter(uint &index, vec3f pos, vec3f vel, vec3f vx,
|
||||
vec3f vy, float r, int n, float lifetime,
|
||||
float lifetimeVariance) {
|
||||
float4 *posPtr = m_pos.getHostPtr();
|
||||
float4 *velPtr = m_vel.getHostPtr();
|
||||
|
||||
uint start = index;
|
||||
uint count = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
vec2f delta = randCircle() * r;
|
||||
|
||||
if (index < m_numParticles) {
|
||||
vec3f p = pos + delta.x * vx + delta.y * vy;
|
||||
float lt = lifetime + frand() * lifetimeVariance;
|
||||
|
||||
posPtr[index] = make_float4(p.x, p.y, p.z, 0.0f);
|
||||
velPtr[index] = make_float4(vel.x, vel.y, vel.z, lt);
|
||||
|
||||
index++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
m_pos.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
m_vel.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
}
|
||||
|
||||
void ParticleSystem::sphereEmitter(uint &index, vec3f pos, vec3f vel,
|
||||
vec3f spread, float r, int n, float lifetime,
|
||||
float lifetimeVariance) {
|
||||
float4 *posPtr = m_pos.getHostPtr();
|
||||
float4 *velPtr = m_vel.getHostPtr();
|
||||
|
||||
uint start = index;
|
||||
uint count = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
vec3f x = randSphere();
|
||||
|
||||
// float dist = length(x);
|
||||
if (index < m_numParticles) {
|
||||
vec3f p = pos + x * r;
|
||||
float age = 0.0;
|
||||
|
||||
float lt = lifetime + frand() * lifetimeVariance;
|
||||
|
||||
vec3f dir = randSphere();
|
||||
dir.y = fabs(dir.y);
|
||||
vec3f v = vel + dir * spread;
|
||||
|
||||
posPtr[index] = make_float4(p.x, p.y, p.z, age);
|
||||
velPtr[index] = make_float4(v.x, v.y, v.z, lt);
|
||||
|
||||
index++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
m_pos.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
m_vel.copy(GpuArray<float4>::HOST_TO_DEVICE, start, count);
|
||||
}
|
||||
|
||||
void ParticleSystem::setModelView(float *m) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
m_modelView.m[i] = m[i];
|
||||
}
|
||||
}
|
||||
|
||||
// dump particles to stdout for debugging
|
||||
void ParticleSystem::dumpParticles(uint start, uint count) {
|
||||
m_pos.copy(GpuArray<float4>::DEVICE_TO_HOST);
|
||||
float4 *pos = m_pos.getHostPtr();
|
||||
|
||||
m_vel.copy(GpuArray<float4>::DEVICE_TO_HOST);
|
||||
float4 *vel = m_vel.getHostPtr();
|
||||
|
||||
for (uint i = start; i < start + count; i++) {
|
||||
printf("%d: ", i);
|
||||
printf("pos: (%.4f, %.4f, %.4f, %.4f)\n", pos[i].x, pos[i].y, pos[i].z,
|
||||
pos[i].w);
|
||||
printf("vel: (%.4f, %.4f, %.4f, %.4f)\n", vel[i].x, vel[i].y, vel[i].z,
|
||||
vel[i].w);
|
||||
}
|
||||
}
|
||||
|
||||
// dump particles to a system memory host
|
||||
void ParticleSystem::dumpBin(float4 **posData, float4 **velData) {
|
||||
m_pos.copy(GpuArray<float4>::DEVICE_TO_HOST);
|
||||
*posData = m_pos.getHostPtr();
|
||||
|
||||
m_vel.copy(GpuArray<float4>::DEVICE_TO_HOST);
|
||||
*velData = m_vel.getHostPtr();
|
||||
}
|
||||
44
Samples/smokeParticles/ParticleSystem.cuh
Normal file
44
Samples/smokeParticles/ParticleSystem.cuh
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#include "particles_kernel.cuh"
|
||||
|
||||
extern "C" {
|
||||
void initCuda(bool bUseGL);
|
||||
void setParameters(SimParams *hostParams);
|
||||
void createNoiseTexture(int w, int h, int d);
|
||||
|
||||
void integrateSystem(float4 *oldPos, float4 *newPos, float4 *oldVel,
|
||||
float4 *newVel, float deltaTime, int numParticles);
|
||||
|
||||
void calcDepth(float4 *pos,
|
||||
float *keys, // output
|
||||
uint *indices, // output
|
||||
float3 sortVector, int numParticles);
|
||||
|
||||
void sortParticles(float *sortKeys, uint *indices, uint numParticles);
|
||||
}
|
||||
112
Samples/smokeParticles/ParticleSystem.h
Normal file
112
Samples/smokeParticles/ParticleSystem.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#ifndef __PARTICLESYSTEM_H__
|
||||
#define __PARTICLESYSTEM_H__
|
||||
|
||||
#include <helper_functions.h>
|
||||
#include "particles_kernel.cuh"
|
||||
#include "vector_functions.h"
|
||||
#include "GpuArray.h"
|
||||
#include "nvMath.h"
|
||||
|
||||
using namespace nv;
|
||||
|
||||
// CUDA BodySystem: runs on the GPU
|
||||
class ParticleSystem {
|
||||
public:
|
||||
ParticleSystem(uint numParticles, bool bUseVBO = true, bool bUseGL = true);
|
||||
~ParticleSystem();
|
||||
|
||||
enum ParticleConfig { CONFIG_RANDOM, CONFIG_GRID, _NUM_CONFIGS };
|
||||
|
||||
void step(float deltaTime);
|
||||
void depthSort();
|
||||
void reset(ParticleConfig config);
|
||||
|
||||
uint getNumParticles() { return m_numParticles; }
|
||||
|
||||
uint getPosBuffer() { return m_pos.getVbo(); }
|
||||
uint getVelBuffer() { return m_vel.getVbo(); }
|
||||
uint getColorBuffer() { return 0; }
|
||||
uint getSortedIndexBuffer() { return m_indices.getVbo(); }
|
||||
uint *getSortedIndices();
|
||||
|
||||
float getParticleRadius() { return m_particleRadius; }
|
||||
|
||||
SimParams &getParams() { return m_params; }
|
||||
|
||||
void setSorting(bool x) { m_doDepthSort = x; }
|
||||
void setModelView(float *m);
|
||||
void setSortVector(float3 v) { m_sortVector = v; }
|
||||
|
||||
void addSphere(uint &index, vec3f pos, vec3f vel, int r, float spacing,
|
||||
float jitter, float lifetime);
|
||||
void discEmitter(uint &index, vec3f pos, vec3f vel, vec3f vx, vec3f vy,
|
||||
float r, int n, float lifetime, float lifetimeVariance);
|
||||
void sphereEmitter(uint &index, vec3f pos, vec3f vel, vec3f spread, float r,
|
||||
int n, float lifetime, float lifetimeVariance);
|
||||
|
||||
void dumpParticles(uint start, uint count);
|
||||
void dumpBin(float4 **posData, float4 **velData);
|
||||
|
||||
protected: // methods
|
||||
ParticleSystem() {}
|
||||
|
||||
void _initialize(int numParticlesm, bool bUseGL = true);
|
||||
void _free();
|
||||
|
||||
void initGrid(vec3f start, uint3 size, vec3f spacing, float jitter, vec3f vel,
|
||||
uint numParticles, float lifetime = 100.0f);
|
||||
void initCubeRandom(vec3f origin, vec3f size, vec3f vel,
|
||||
float lifetime = 100.0f);
|
||||
|
||||
protected: // data
|
||||
bool m_bInitialized;
|
||||
bool m_bUseVBO;
|
||||
uint m_numParticles;
|
||||
|
||||
float m_particleRadius;
|
||||
|
||||
GpuArray<float4> m_pos;
|
||||
GpuArray<float4> m_vel;
|
||||
|
||||
// params
|
||||
SimParams m_params;
|
||||
|
||||
float4x4 m_modelView;
|
||||
float3 m_sortVector;
|
||||
bool m_doDepthSort;
|
||||
|
||||
GpuArray<float> m_sortKeys;
|
||||
GpuArray<uint> m_indices; // sorted indices for rendering
|
||||
|
||||
StopWatchInterface *m_timer;
|
||||
float m_time;
|
||||
};
|
||||
|
||||
#endif // __PARTICLESYSTEM_H__
|
||||
151
Samples/smokeParticles/ParticleSystem_cuda.cu
Normal file
151
Samples/smokeParticles/ParticleSystem_cuda.cu
Normal file
@@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains simple wrapper functions that call the CUDA kernels
|
||||
*/
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include <helper_cuda.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <string.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include "thrust/device_ptr.h"
|
||||
#include "thrust/for_each.h"
|
||||
#include "thrust/iterator/zip_iterator.h"
|
||||
#include "thrust/sort.h"
|
||||
|
||||
#include "particles_kernel_device.cuh"
|
||||
#include "ParticleSystem.cuh"
|
||||
|
||||
extern "C" {
|
||||
|
||||
cudaArray *noiseArray;
|
||||
|
||||
void setParameters(SimParams *hostParams) {
|
||||
// copy parameters to constant memory
|
||||
checkCudaErrors(cudaMemcpyToSymbol(params, hostParams, sizeof(SimParams)));
|
||||
}
|
||||
|
||||
// Round a / b to nearest higher integer value
|
||||
int iDivUp(int a, int b) { return (a % b != 0) ? (a / b + 1) : (a / b); }
|
||||
|
||||
// compute grid and thread block size for a given number of elements
|
||||
void computeGridSize(int n, int blockSize, int &numBlocks, int &numThreads) {
|
||||
numThreads = min(blockSize, n);
|
||||
numBlocks = iDivUp(n, numThreads);
|
||||
}
|
||||
|
||||
inline float frand() { return rand() / (float)RAND_MAX; }
|
||||
|
||||
// create 3D texture containing random values
|
||||
void createNoiseTexture(int w, int h, int d) {
|
||||
cudaExtent size = make_cudaExtent(w, h, d);
|
||||
size_t elements = size.width * size.height * size.depth;
|
||||
|
||||
float *volumeData = (float *)malloc(elements * 4 * sizeof(float));
|
||||
float *ptr = volumeData;
|
||||
|
||||
for (size_t i = 0; i < elements; i++) {
|
||||
*ptr++ = frand() * 2.0f - 1.0f;
|
||||
*ptr++ = frand() * 2.0f - 1.0f;
|
||||
*ptr++ = frand() * 2.0f - 1.0f;
|
||||
*ptr++ = frand() * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float4>();
|
||||
checkCudaErrors(cudaMalloc3DArray(&noiseArray, &channelDesc, size));
|
||||
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.srcPtr = make_cudaPitchedPtr(
|
||||
(void *)volumeData, size.width * sizeof(float4), size.width, size.height);
|
||||
copyParams.dstArray = noiseArray;
|
||||
copyParams.extent = size;
|
||||
copyParams.kind = cudaMemcpyHostToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
|
||||
free(volumeData);
|
||||
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = noiseArray;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = true;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.addressMode[0] = cudaAddressModeWrap;
|
||||
texDescr.addressMode[1] = cudaAddressModeWrap;
|
||||
texDescr.addressMode[2] = cudaAddressModeWrap;
|
||||
texDescr.readMode = cudaReadModeElementType;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&noiseTex, &texRes, &texDescr, NULL));
|
||||
}
|
||||
|
||||
void integrateSystem(float4 *oldPos, float4 *newPos, float4 *oldVel,
|
||||
float4 *newVel, float deltaTime, int numParticles) {
|
||||
thrust::device_ptr<float4> d_newPos(newPos);
|
||||
thrust::device_ptr<float4> d_newVel(newVel);
|
||||
thrust::device_ptr<float4> d_oldPos(oldPos);
|
||||
thrust::device_ptr<float4> d_oldVel(oldVel);
|
||||
|
||||
thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(
|
||||
d_newPos, d_newVel, d_oldPos, d_oldVel)),
|
||||
thrust::make_zip_iterator(thrust::make_tuple(
|
||||
d_newPos + numParticles, d_newVel + numParticles,
|
||||
d_oldPos + numParticles, d_oldVel + numParticles)),
|
||||
integrate_functor(deltaTime, noiseTex));
|
||||
}
|
||||
|
||||
void calcDepth(float4 *pos,
|
||||
float *keys, // output
|
||||
uint *indices, // output
|
||||
float3 sortVector, int numParticles) {
|
||||
thrust::device_ptr<float4> d_pos(pos);
|
||||
thrust::device_ptr<float> d_keys(keys);
|
||||
thrust::device_ptr<uint> d_indices(indices);
|
||||
|
||||
thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(d_pos, d_keys)),
|
||||
thrust::make_zip_iterator(thrust::make_tuple(
|
||||
d_pos + numParticles, d_keys + numParticles)),
|
||||
calcDepth_functor(sortVector));
|
||||
|
||||
thrust::sequence(d_indices, d_indices + numParticles);
|
||||
}
|
||||
|
||||
void sortParticles(float *sortKeys, uint *indices, uint numParticles) {
|
||||
thrust::sort_by_key(thrust::device_ptr<float>(sortKeys),
|
||||
thrust::device_ptr<float>(sortKeys + numParticles),
|
||||
thrust::device_ptr<uint>(indices));
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
74
Samples/smokeParticles/README.md
Normal file
74
Samples/smokeParticles/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# smokeParticles - Smoke Particles
|
||||
|
||||
## Description
|
||||
|
||||
Smoke simulation with volumetric shadows using half-angle slicing technique. Uses CUDA for procedural simulation, Thrust Library for sorting algorithms, and OpenGL for graphics rendering.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
Graphics Interop, Data Parallel Algorithms, Physically-Based Simulation
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](https://developer.nvidia.com/cuda-gpus) [SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus) [SM 8.0 ](https://developer.nvidia.com/cuda-gpus) [SM 8.6 ](https://developer.nvidia.com/cuda-gpus)
|
||||
|
||||
## Supported OSes
|
||||
|
||||
Linux, Windows
|
||||
|
||||
## Supported CPU Architecture
|
||||
|
||||
x86_64, armv7l
|
||||
|
||||
## CUDA APIs involved
|
||||
|
||||
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
|
||||
cudaGraphicsMapResources, cudaGraphicsUnmapResources, cudaGraphicsResourceGetMappedPointer, cudaGraphicsRegisterResource, cudaGraphicsGLRegisterBuffer, cudaGraphicsUnregisterResource
|
||||
|
||||
## Dependencies needed to build/run
|
||||
[X11](../../README.md#x11), [GL](../../README.md#gl)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and install the [CUDA Toolkit 11.5](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
|
||||
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
|
||||
|
||||
## Build and Run
|
||||
|
||||
### Windows
|
||||
The Windows samples are built using the Visual Studio IDE. Solution files (.sln) are provided for each supported version of Visual Studio, using the format:
|
||||
```
|
||||
*_vs<version>.sln - for Visual Studio <version>
|
||||
```
|
||||
Each individual sample has its own set of solution files in its directory:
|
||||
|
||||
To build/examine all the samples at once, the complete solution files should be used. To build/examine a single sample, the individual sample solution files should be used.
|
||||
> **Note:** Some samples require that the Microsoft DirectX SDK (June 2010 or newer) be installed and that the VC++ directory paths are properly set up (**Tools > Options...**). Check DirectX Dependencies section for details."
|
||||
|
||||
### Linux
|
||||
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
|
||||
```
|
||||
$ cd <sample_dir>
|
||||
$ make
|
||||
```
|
||||
The samples makefiles can take advantage of certain options:
|
||||
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, armv7l.
|
||||
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
|
||||
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=armv7l` <br/>
|
||||
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
|
||||
* **dbg=1** - build with debug symbols
|
||||
```
|
||||
$ make dbg=1
|
||||
```
|
||||
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
|
||||
```
|
||||
$ make SMS="50 60"
|
||||
```
|
||||
|
||||
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
|
||||
```
|
||||
$ make HOST_COMPILER=g++
|
||||
```
|
||||
|
||||
## References (for more details)
|
||||
|
||||
567
Samples/smokeParticles/SmokeRenderer.cpp
Normal file
567
Samples/smokeParticles/SmokeRenderer.cpp
Normal file
@@ -0,0 +1,567 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This class renders particles using OpenGL and GLSL shaders
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include "SmokeRenderer.h"
|
||||
#include "SmokeShaders.h"
|
||||
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
|
||||
#define USE_MBLUR 1
|
||||
#define COLOR_ATTENUATION 1
|
||||
|
||||
SmokeRenderer::SmokeRenderer(int maxParticles)
|
||||
: mMaxParticles(maxParticles),
|
||||
mNumParticles(0),
|
||||
mPosVbo(0),
|
||||
mVelVbo(0),
|
||||
mColorVbo(0),
|
||||
mIndexBuffer(0),
|
||||
mParticleRadius(0.005f),
|
||||
mDisplayMode(VOLUMETRIC),
|
||||
mWindowW(800),
|
||||
mWindowH(600),
|
||||
mFov(40.0f),
|
||||
m_downSample(2),
|
||||
m_numSlices(32),
|
||||
m_numDisplayedSlices(32),
|
||||
m_sliceNo(0),
|
||||
m_shadowAlpha(0.005f),
|
||||
m_spriteAlpha(0.1f),
|
||||
m_doBlur(false),
|
||||
m_blurRadius(1.0f),
|
||||
m_displayLightBuffer(false),
|
||||
m_lightPos(5.0f, 5.0f, -5.0f),
|
||||
m_lightTarget(0.0f, 0.0f, 0.0f),
|
||||
m_lightColor(1.0f, 1.0f, 0.5f),
|
||||
m_colorAttenuation(0.1f, 0.2f, 0.3f),
|
||||
m_lightBufferSize(256),
|
||||
m_srcLightTexture(0),
|
||||
m_lightDepthTexture(0),
|
||||
m_lightFbo(0),
|
||||
m_imageTex(0),
|
||||
m_depthTex(0),
|
||||
m_imageFbo(0) {
|
||||
// load shader programs
|
||||
m_simpleProg = new GLSLProgram(particleVS, simplePS);
|
||||
m_particleProg = new GLSLProgram(mblurVS, mblurGS, particlePS);
|
||||
m_particleShadowProg = new GLSLProgram(mblurVS, mblurGS, particleShadowPS);
|
||||
|
||||
m_blurProg = new GLSLProgram(passThruVS, blurPS);
|
||||
m_displayTexProg = new GLSLProgram(passThruVS, texture2DPS);
|
||||
|
||||
// create buffer for light shadows
|
||||
createLightBuffer();
|
||||
|
||||
glutReportErrors();
|
||||
}
|
||||
|
||||
SmokeRenderer::~SmokeRenderer() {
|
||||
delete m_particleProg;
|
||||
delete m_particleShadowProg;
|
||||
delete m_blurProg;
|
||||
delete m_displayTexProg;
|
||||
delete m_simpleProg;
|
||||
|
||||
delete m_lightFbo;
|
||||
glDeleteTextures(2, m_lightTexture);
|
||||
glDeleteTextures(1, &m_lightDepthTexture);
|
||||
|
||||
delete m_imageFbo;
|
||||
glDeleteTextures(1, &m_imageTex);
|
||||
glDeleteTextures(1, &m_depthTex);
|
||||
}
|
||||
|
||||
// draw points from vertex buffer objects
|
||||
void SmokeRenderer::drawPoints(int start, int count, bool sort) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mPosVbo);
|
||||
glVertexPointer(4, GL_FLOAT, 0, 0);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (mColorVbo) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mColorVbo);
|
||||
glColorPointer(4, GL_FLOAT, 0, 0);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (mVelVbo) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mVelVbo);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(4, GL_FLOAT, 0, 0);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, mIndexBuffer);
|
||||
glDrawElements(GL_POINTS, count, GL_UNSIGNED_INT,
|
||||
(void *)(start * sizeof(unsigned int)));
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||
} else {
|
||||
glDrawArrays(GL_POINTS, start, count);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
// draw points using given shader program
|
||||
void SmokeRenderer::drawPointSprites(GLSLProgram *prog, int start, int count,
|
||||
bool shadowed) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE); // don't write depth
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
prog->enable();
|
||||
prog->setUniform1f("pointRadius", mParticleRadius);
|
||||
|
||||
if (shadowed) {
|
||||
prog->bindTexture("shadowTex", m_lightTexture[m_srcLightTexture],
|
||||
GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// draw points
|
||||
drawPoints(start, count, true);
|
||||
|
||||
prog->disable();
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
// calculate vectors for half-angle slice rendering
|
||||
void SmokeRenderer::calcVectors() {
|
||||
// get model view matrix
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, (float *)m_modelView.get_value());
|
||||
|
||||
// calculate eye space light vector
|
||||
m_lightVector = normalize(m_lightPos);
|
||||
m_lightPosEye = m_modelView * vec4f(m_lightPos, 1.0);
|
||||
|
||||
// calculate half-angle vector between view and light
|
||||
m_viewVector = -vec3f(m_modelView.get_row(2));
|
||||
|
||||
if (dot(m_viewVector, m_lightVector) > 0) {
|
||||
m_halfVector = normalize(m_viewVector + m_lightVector);
|
||||
m_invertedView = false;
|
||||
} else {
|
||||
m_halfVector = normalize(-m_viewVector + m_lightVector);
|
||||
m_invertedView = true;
|
||||
}
|
||||
|
||||
// calculate light view matrix
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluLookAt(m_lightPos[0], m_lightPos[1], m_lightPos[2], m_lightTarget[0],
|
||||
m_lightTarget[1], m_lightTarget[2], 0.0, 1.0, 0.0);
|
||||
|
||||
// calculate light projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, 1.0, 1.0, 200.0);
|
||||
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, (float *)m_lightView.get_value());
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, (float *)m_lightProj.get_value());
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
// construct shadow matrix
|
||||
matrix4f scale;
|
||||
scale.set_scale(vec3f(0.5, 0.5, 0.5));
|
||||
matrix4f translate;
|
||||
translate.set_translate(vec3f(0.5, 0.5, 0.5));
|
||||
|
||||
m_shadowMatrix =
|
||||
translate * scale * m_lightProj * m_lightView * inverse(m_modelView);
|
||||
|
||||
// calc object space eye position
|
||||
m_eyePos = inverse(m_modelView) * vec4f(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
// calc half vector in eye space
|
||||
m_halfVectorEye = m_modelView * vec4f(m_halfVector, 0.0);
|
||||
}
|
||||
|
||||
// draw slice of particles from camera view
|
||||
void SmokeRenderer::drawSlice(int i) {
|
||||
m_imageFbo->Bind();
|
||||
glViewport(0, 0, m_imageW, m_imageH);
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, m_spriteAlpha);
|
||||
|
||||
if (m_invertedView) {
|
||||
// front-to-back
|
||||
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
|
||||
} else {
|
||||
// back-to-front
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
drawPointSprites(m_particleShadowProg, i * m_batchSize, m_batchSize, true);
|
||||
|
||||
m_imageFbo->Disable();
|
||||
}
|
||||
|
||||
// draw slice of particles from light's point of view
|
||||
void SmokeRenderer::drawSliceLightView(int i) {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf((GLfloat *)m_lightView.get_value());
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf((GLfloat *)m_lightProj.get_value());
|
||||
|
||||
m_lightFbo->Bind();
|
||||
glViewport(0, 0, m_lightBufferSize, m_lightBufferSize);
|
||||
|
||||
glColor4f(m_colorAttenuation[0] * m_shadowAlpha,
|
||||
m_colorAttenuation[1] * m_shadowAlpha,
|
||||
m_colorAttenuation[2] * m_shadowAlpha, 1.0);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
drawPointSprites(m_particleProg, i * m_batchSize, m_batchSize, false);
|
||||
|
||||
m_lightFbo->Disable();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// draw particles as slices with shadowing
|
||||
void SmokeRenderer::drawSlices() {
|
||||
m_batchSize = mNumParticles / m_numSlices;
|
||||
|
||||
// clear light buffer
|
||||
m_srcLightTexture = 0;
|
||||
m_lightFbo->Bind();
|
||||
m_lightFbo->AttachTexture(GL_TEXTURE_2D, m_lightTexture[m_srcLightTexture],
|
||||
GL_COLOR_ATTACHMENT0_EXT);
|
||||
glClearColor(1.0f - m_lightColor[0], 1.0f - m_lightColor[1],
|
||||
1.0f - m_lightColor[2], 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_lightFbo->Disable();
|
||||
|
||||
// clear volume image
|
||||
m_imageFbo->Bind();
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_imageFbo->Disable();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf((GLfloat *)m_shadowMatrix.get_value());
|
||||
|
||||
// render slices
|
||||
if (m_numDisplayedSlices > m_numSlices) m_numDisplayedSlices = m_numSlices;
|
||||
|
||||
for (int i = 0; i < m_numDisplayedSlices; i++) {
|
||||
// draw slice from camera view, sampling light buffer
|
||||
drawSlice(i);
|
||||
// draw slice from light view to light buffer, accumulating shadows
|
||||
drawSliceLightView(i);
|
||||
|
||||
if (m_doBlur) {
|
||||
blurLightBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
// blur light buffer to simulate scattering effects
|
||||
void SmokeRenderer::blurLightBuffer() {
|
||||
m_lightFbo->Bind();
|
||||
m_lightFbo->AttachTexture(GL_TEXTURE_2D,
|
||||
m_lightTexture[1 - m_srcLightTexture],
|
||||
GL_COLOR_ATTACHMENT0_EXT);
|
||||
glViewport(0, 0, m_lightBufferSize, m_lightBufferSize);
|
||||
|
||||
m_blurProg->enable();
|
||||
m_blurProg->bindTexture("tex", m_lightTexture[m_srcLightTexture],
|
||||
GL_TEXTURE_2D, 0);
|
||||
m_blurProg->setUniform2f("texelSize", 1.0f / (float)m_lightBufferSize,
|
||||
1.0f / (float)m_lightBufferSize);
|
||||
m_blurProg->setUniform1f("blurRadius", m_blurRadius);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
drawQuad();
|
||||
m_blurProg->disable();
|
||||
|
||||
m_srcLightTexture = 1 - m_srcLightTexture;
|
||||
|
||||
m_lightFbo->Disable();
|
||||
}
|
||||
|
||||
// display texture to screen
|
||||
void SmokeRenderer::displayTexture(GLuint tex) {
|
||||
m_displayTexProg->enable();
|
||||
m_displayTexProg->bindTexture("tex", tex, GL_TEXTURE_2D, 0);
|
||||
drawQuad();
|
||||
m_displayTexProg->disable();
|
||||
}
|
||||
|
||||
// composite final volume image on top of scene
|
||||
void SmokeRenderer::compositeResult() {
|
||||
glViewport(0, 0, mWindowW, mWindowH);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
displayTexture(m_imageTex);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void SmokeRenderer::render() {
|
||||
switch (mDisplayMode) {
|
||||
case POINTS:
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
m_simpleProg->enable();
|
||||
drawPoints(0, mNumParticles, false);
|
||||
m_simpleProg->disable();
|
||||
break;
|
||||
|
||||
case SPRITES:
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
glColor4f(1.0, 1.0, 1.0, m_spriteAlpha);
|
||||
drawPointSprites(m_particleProg, 0, mNumParticles, false);
|
||||
break;
|
||||
|
||||
case VOLUMETRIC:
|
||||
drawSlices();
|
||||
compositeResult();
|
||||
break;
|
||||
|
||||
case NUM_MODES:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_displayLightBuffer) {
|
||||
// display light buffer to screen
|
||||
glViewport(0, 0, m_lightBufferSize, m_lightBufferSize);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
displayTexture(m_lightTexture[m_srcLightTexture]);
|
||||
glViewport(0, 0, mWindowW, mWindowH);
|
||||
}
|
||||
|
||||
glutReportErrors();
|
||||
}
|
||||
|
||||
// render scene depth to texture
|
||||
// (this is to ensure that particle are correctly occluded in the low-resolution
|
||||
// render buffer)
|
||||
void SmokeRenderer::beginSceneRender(Target target) {
|
||||
if (target == LIGHT_BUFFER) {
|
||||
m_lightFbo->Bind();
|
||||
glViewport(0, 0, m_lightBufferSize, m_lightBufferSize);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf((GLfloat *)m_lightView.get_value());
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf((GLfloat *)m_lightProj.get_value());
|
||||
} else {
|
||||
m_imageFbo->Bind();
|
||||
glViewport(0, 0, m_imageW, m_imageH);
|
||||
}
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void SmokeRenderer::endSceneRender(Target target) {
|
||||
if (target == LIGHT_BUFFER) {
|
||||
m_lightFbo->Disable();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
} else {
|
||||
m_imageFbo->Disable();
|
||||
}
|
||||
|
||||
glViewport(0, 0, mWindowW, mWindowH);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
}
|
||||
|
||||
// create an OpenGL texture
|
||||
GLuint SmokeRenderer::createTexture(GLenum target, int w, int h,
|
||||
GLint internalformat, GLenum format) {
|
||||
GLuint texid;
|
||||
glGenTextures(1, &texid);
|
||||
glBindTexture(target, texid);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(target, 0, internalformat, w, h, 0, format, GL_FLOAT, 0);
|
||||
return texid;
|
||||
}
|
||||
|
||||
// create buffers for off-screen rendering
|
||||
void SmokeRenderer::createBuffers(int w, int h) {
|
||||
if (m_imageFbo) {
|
||||
glDeleteTextures(1, &m_imageTex);
|
||||
glDeleteTextures(1, &m_depthTex);
|
||||
delete m_imageFbo;
|
||||
}
|
||||
|
||||
mWindowW = w;
|
||||
mWindowH = h;
|
||||
|
||||
m_imageW = w / m_downSample;
|
||||
m_imageH = h / m_downSample;
|
||||
|
||||
// create fbo for image buffer
|
||||
GLint format = GL_RGBA16F_ARB;
|
||||
// GLint format = GL_LUMINANCE16F_ARB;
|
||||
// GLint format = GL_RGBA8;
|
||||
m_imageTex =
|
||||
createTexture(GL_TEXTURE_2D, m_imageW, m_imageH, format, GL_RGBA);
|
||||
m_depthTex = createTexture(GL_TEXTURE_2D, m_imageW, m_imageH,
|
||||
GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
m_imageFbo = new FramebufferObject();
|
||||
m_imageFbo->AttachTexture(GL_TEXTURE_2D, m_imageTex,
|
||||
GL_COLOR_ATTACHMENT0_EXT);
|
||||
m_imageFbo->AttachTexture(GL_TEXTURE_2D, m_depthTex, GL_DEPTH_ATTACHMENT_EXT);
|
||||
m_imageFbo->IsValid();
|
||||
}
|
||||
|
||||
void SmokeRenderer::setLightColor(vec3f c) {
|
||||
m_lightColor = c;
|
||||
|
||||
// set light texture border color
|
||||
GLfloat borderColor[4] = {1.0f - m_lightColor[0], 1.0f - m_lightColor[1],
|
||||
1.0f - m_lightColor[2], 0.0f};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_lightTexture[0]);
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_lightTexture[1]);
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// create FBOs for light buffer
|
||||
void SmokeRenderer::createLightBuffer() {
|
||||
GLint format = GL_RGBA16F_ARB;
|
||||
// GLint format = GL_RGBA8;
|
||||
// GLint format = GL_LUMINANCE16F_ARB;
|
||||
|
||||
m_lightTexture[0] = createTexture(GL_TEXTURE_2D, m_lightBufferSize,
|
||||
m_lightBufferSize, format, GL_RGBA);
|
||||
// make shadows clamp to light color at edges
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
m_lightTexture[1] = createTexture(GL_TEXTURE_2D, m_lightBufferSize,
|
||||
m_lightBufferSize, format, GL_RGBA);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
m_lightDepthTexture =
|
||||
createTexture(GL_TEXTURE_2D, m_lightBufferSize, m_lightBufferSize,
|
||||
GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT);
|
||||
|
||||
m_lightFbo = new FramebufferObject();
|
||||
m_lightFbo->AttachTexture(GL_TEXTURE_2D, m_lightTexture[m_srcLightTexture],
|
||||
GL_COLOR_ATTACHMENT0_EXT);
|
||||
m_lightFbo->AttachTexture(GL_TEXTURE_2D, m_lightDepthTexture,
|
||||
GL_DEPTH_ATTACHMENT_EXT);
|
||||
m_lightFbo->IsValid();
|
||||
}
|
||||
|
||||
void SmokeRenderer::setWindowSize(int w, int h) {
|
||||
mAspect = (float)mWindowW / (float)mWindowH;
|
||||
mInvFocalLen = tan(mFov * 0.5f * NV_PI / 180.0f);
|
||||
|
||||
createBuffers(w, h);
|
||||
}
|
||||
|
||||
void SmokeRenderer::drawQuad() {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex2f(-1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex2f(1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex2f(1.0f, 1.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex2f(-1.0f, 1.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void SmokeRenderer::drawVector(vec3f v) {
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
glVertex3fv((float *)&v[0]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// render vectors to screen for debugging
|
||||
void SmokeRenderer::debugVectors() {
|
||||
glColor3f(1.0f, 1.0f, 0.0f);
|
||||
drawVector(m_lightVector);
|
||||
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
drawVector(m_viewVector);
|
||||
|
||||
glColor3f(0.0f, 0.0f, 1.0f);
|
||||
drawVector(-m_viewVector);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
drawVector(m_halfVector);
|
||||
}
|
||||
168
Samples/smokeParticles/SmokeRenderer.h
Normal file
168
Samples/smokeParticles/SmokeRenderer.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
// Smoke particle renderer with volumetric shadows
|
||||
|
||||
#ifndef SMOKE_RENDERER_H
|
||||
#define SMOKE_RENDERER_H
|
||||
|
||||
#include "framebufferObject.h"
|
||||
#include "GLSLProgram.h"
|
||||
#include "nvMath.h"
|
||||
|
||||
using namespace nv;
|
||||
|
||||
class SmokeRenderer {
|
||||
public:
|
||||
SmokeRenderer(int maxParticles);
|
||||
~SmokeRenderer();
|
||||
|
||||
enum DisplayMode { POINTS, SPRITES, VOLUMETRIC, NUM_MODES };
|
||||
|
||||
enum Target { LIGHT_BUFFER, SCENE_BUFFER };
|
||||
|
||||
void setDisplayMode(DisplayMode mode) { mDisplayMode = mode; }
|
||||
|
||||
void setNumParticles(unsigned int x) { mNumParticles = x; }
|
||||
void setPositionBuffer(GLuint vbo) { mPosVbo = vbo; }
|
||||
void setVelocityBuffer(GLuint vbo) { mVelVbo = vbo; }
|
||||
void setColorBuffer(GLuint vbo) { mColorVbo = vbo; }
|
||||
void setIndexBuffer(GLuint ib) { mIndexBuffer = ib; }
|
||||
|
||||
void setParticleRadius(float x) { mParticleRadius = x; }
|
||||
void setWindowSize(int w, int h);
|
||||
void setFOV(float fov) { mFov = fov; }
|
||||
|
||||
void setNumSlices(int x) { m_numSlices = x; }
|
||||
void setNumDisplayedSlices(int x) { m_numDisplayedSlices = x; }
|
||||
|
||||
void setAlpha(float x) { m_spriteAlpha = x; }
|
||||
void setShadowAlpha(float x) { m_shadowAlpha = x; }
|
||||
void setColorAttenuation(vec3f c) { m_colorAttenuation = c; }
|
||||
void setLightColor(vec3f c);
|
||||
|
||||
void setDoBlur(bool b) { m_doBlur = b; }
|
||||
void setBlurRadius(float x) { m_blurRadius = x; }
|
||||
void setDisplayLightBuffer(bool b) { m_displayLightBuffer = b; }
|
||||
|
||||
void beginSceneRender(Target target);
|
||||
void endSceneRender(Target target);
|
||||
|
||||
void setLightPosition(vec3f v) { m_lightPos = v; }
|
||||
void setLightTarget(vec3f v) { m_lightTarget = v; }
|
||||
|
||||
vec4f getLightPositionEyeSpace() { return m_lightPosEye; }
|
||||
matrix4f getShadowMatrix() { return m_shadowMatrix; }
|
||||
|
||||
GLuint getShadowTexture() { return m_lightTexture[m_srcLightTexture]; }
|
||||
|
||||
void calcVectors();
|
||||
vec3f getSortVector() { return m_halfVector; }
|
||||
|
||||
void render();
|
||||
void debugVectors();
|
||||
|
||||
private:
|
||||
void drawPoints(int start, int count, bool sort);
|
||||
void drawPointSprites(GLSLProgram *prog, int start, int count, bool shadowed);
|
||||
|
||||
void drawSlice(int i);
|
||||
void drawSliceLightView(int i);
|
||||
void drawSlices();
|
||||
void displayTexture(GLuint tex);
|
||||
void compositeResult();
|
||||
void blurLightBuffer();
|
||||
void depthSort();
|
||||
|
||||
GLuint createTexture(GLenum target, int w, int h, GLint internalformat,
|
||||
GLenum format);
|
||||
void createBuffers(int w, int h);
|
||||
void createLightBuffer();
|
||||
|
||||
void drawQuad();
|
||||
void drawVector(vec3f v);
|
||||
|
||||
// particle data
|
||||
unsigned int mMaxParticles;
|
||||
unsigned int mNumParticles;
|
||||
|
||||
GLuint mPosVbo;
|
||||
GLuint mVelVbo;
|
||||
GLuint mColorVbo;
|
||||
GLuint mIndexBuffer;
|
||||
|
||||
float mParticleRadius;
|
||||
DisplayMode mDisplayMode;
|
||||
|
||||
// window
|
||||
unsigned int mWindowW, mWindowH;
|
||||
float mAspect, mInvFocalLen;
|
||||
float mFov;
|
||||
|
||||
int m_downSample;
|
||||
int m_imageW, m_imageH;
|
||||
|
||||
int m_numSlices;
|
||||
int m_numDisplayedSlices;
|
||||
int m_batchSize;
|
||||
int m_sliceNo;
|
||||
|
||||
float m_shadowAlpha;
|
||||
float m_spriteAlpha;
|
||||
bool m_doBlur;
|
||||
float m_blurRadius;
|
||||
bool m_displayLightBuffer;
|
||||
|
||||
vec3f m_lightVector, m_lightPos, m_lightTarget;
|
||||
vec3f m_lightColor;
|
||||
vec3f m_colorAttenuation;
|
||||
float m_lightDistance;
|
||||
|
||||
matrix4f m_modelView, m_lightView, m_lightProj, m_shadowMatrix;
|
||||
vec3f m_viewVector, m_halfVector;
|
||||
bool m_invertedView;
|
||||
vec4f m_eyePos;
|
||||
vec4f m_halfVectorEye;
|
||||
vec4f m_lightPosEye;
|
||||
|
||||
// programs
|
||||
GLSLProgram *m_simpleProg;
|
||||
GLSLProgram *m_particleProg, *m_particleShadowProg;
|
||||
GLSLProgram *m_displayTexProg, *m_blurProg;
|
||||
|
||||
// image buffers
|
||||
int m_lightBufferSize;
|
||||
GLuint m_lightTexture[2];
|
||||
int m_srcLightTexture;
|
||||
GLuint m_lightDepthTexture;
|
||||
FramebufferObject *m_lightFbo;
|
||||
|
||||
GLuint m_imageTex, m_depthTex;
|
||||
FramebufferObject *m_imageFbo;
|
||||
};
|
||||
|
||||
#endif
|
||||
304
Samples/smokeParticles/SmokeShaders.cpp
Normal file
304
Samples/smokeParticles/SmokeShaders.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/* Copyright (c) 2021, 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
|
||||
);
|
||||
32
Samples/smokeParticles/SmokeShaders.h
Normal file
32
Samples/smokeParticles/SmokeShaders.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
extern const char *particleVS;
|
||||
extern const char *particleSpherePS, *simplePS, *particlePS, *particleShadowPS;
|
||||
extern const char *mblurVS, *mblurGS;
|
||||
extern const char *passThruVS, *texture2DPS, *blurPS;
|
||||
extern const char *floorVS, *floorPS;
|
||||
BIN
Samples/smokeParticles/data/floortile.ppm
Normal file
BIN
Samples/smokeParticles/data/floortile.ppm
Normal file
Binary file not shown.
BIN
Samples/smokeParticles/data/ref_smokePart_pos.bin
Normal file
BIN
Samples/smokeParticles/data/ref_smokePart_pos.bin
Normal file
Binary file not shown.
BIN
Samples/smokeParticles/data/ref_smokePart_vel.bin
Normal file
BIN
Samples/smokeParticles/data/ref_smokePart_vel.bin
Normal file
Binary file not shown.
BIN
Samples/smokeParticles/doc/screenshot_lg.png
Normal file
BIN
Samples/smokeParticles/doc/screenshot_lg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 214 KiB |
BIN
Samples/smokeParticles/doc/screenshot_md.png
Normal file
BIN
Samples/smokeParticles/doc/screenshot_md.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
Samples/smokeParticles/doc/screenshot_sm.png
Normal file
BIN
Samples/smokeParticles/doc/screenshot_sm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
Samples/smokeParticles/doc/smokeParticles.doc
Normal file
BIN
Samples/smokeParticles/doc/smokeParticles.doc
Normal file
Binary file not shown.
BIN
Samples/smokeParticles/doc/smokeParticles.pdf
Normal file
BIN
Samples/smokeParticles/doc/smokeParticles.pdf
Normal file
Binary file not shown.
145
Samples/smokeParticles/findgllib.mk
Normal file
145
Samples/smokeParticles/findgllib.mk
Normal file
@@ -0,0 +1,145 @@
|
||||
################################################################################
|
||||
# Copyright (c) 2020, 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.
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# findgllib.mk is used to find the necessary GL Libraries for specific distributions
|
||||
# this is supported on Mac OSX and Linux Platforms
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Determine OS platform and unix distribution
|
||||
ifeq ("$(TARGET_OS)","linux")
|
||||
# first search lsb_release
|
||||
DISTRO := $(shell lsb_release -i -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
|
||||
ifeq ("$(DISTRO)","")
|
||||
# second search and parse /etc/issue
|
||||
DISTRO := $(shell awk '{print $$1}' /etc/issue | tr -d "[:space:]" | sed -e "/^$$/d" | tr "[:upper:]" "[:lower:]")
|
||||
# ensure data from /etc/issue is valid
|
||||
ifeq (,$(filter $(DISTRO),ubuntu fedora red rhel centos suse))
|
||||
DISTRO :=
|
||||
endif
|
||||
ifeq ("$(DISTRO)","")
|
||||
# third, we can search in /etc/os-release or /etc/{distro}-release
|
||||
DISTRO := $(shell awk '/ID/' /etc/*-release | sed 's/ID=//' | grep -v "VERSION" | grep -v "ID" | grep -v "DISTRIB")
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ("$(TARGET_OS)","linux")
|
||||
# $(info) >> findgllib.mk -> LINUX path <<<)
|
||||
# Each set of Linux Distros have different paths for where to find their OpenGL libraries reside
|
||||
UBUNTU = $(shell echo $(DISTRO) | grep -i ubuntu >/dev/null 2>&1; echo $$?)
|
||||
FEDORA = $(shell echo $(DISTRO) | grep -i fedora >/dev/null 2>&1; echo $$?)
|
||||
RHEL = $(shell echo $(DISTRO) | grep -i 'red\|rhel' >/dev/null 2>&1; echo $$?)
|
||||
CENTOS = $(shell echo $(DISTRO) | grep -i centos >/dev/null 2>&1; echo $$?)
|
||||
SUSE = $(shell echo $(DISTRO) | grep -i 'suse\|sles' >/dev/null 2>&1; echo $$?)
|
||||
ifeq ("$(UBUNTU)","0")
|
||||
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
|
||||
GLPATH := /usr/arm-linux-gnueabihf/lib
|
||||
GLLINK := -L/usr/arm-linux-gnueabihf/lib
|
||||
ifneq ($(TARGET_FS),)
|
||||
GLPATH += $(TARGET_FS)/usr/lib/arm-linux-gnueabihf
|
||||
GLLINK += -L$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
|
||||
endif
|
||||
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-aarch64)
|
||||
GLPATH := /usr/aarch64-linux-gnu/lib
|
||||
GLLINK := -L/usr/aarch64-linux-gnu/lib
|
||||
ifneq ($(TARGET_FS),)
|
||||
GLPATH += $(TARGET_FS)/usr/lib
|
||||
GLPATH += $(TARGET_FS)/usr/lib/aarch64-linux-gnu
|
||||
GLLINK += -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
|
||||
endif
|
||||
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-ppc64le)
|
||||
GLPATH := /usr/powerpc64le-linux-gnu/lib
|
||||
GLLINK := -L/usr/powerpc64le-linux-gnu/lib
|
||||
else
|
||||
UBUNTU_PKG_NAME = $(shell which dpkg >/dev/null 2>&1 && dpkg -l 'nvidia-*' | grep '^ii' | awk '{print $$2}' | head -1)
|
||||
ifneq ("$(UBUNTU_PKG_NAME)","")
|
||||
GLPATH ?= /usr/lib/$(UBUNTU_PKG_NAME)
|
||||
GLLINK ?= -L/usr/lib/$(UBUNTU_PKG_NAME)
|
||||
endif
|
||||
|
||||
DFLT_PATH ?= /usr/lib
|
||||
endif
|
||||
endif
|
||||
ifeq ("$(SUSE)","0")
|
||||
GLPATH ?= /usr/X11R6/lib64
|
||||
GLLINK ?= -L/usr/X11R6/lib64
|
||||
DFLT_PATH ?= /usr/lib64
|
||||
endif
|
||||
ifeq ("$(FEDORA)","0")
|
||||
GLPATH ?= /usr/lib64/nvidia
|
||||
GLLINK ?= -L/usr/lib64/nvidia
|
||||
DFLT_PATH ?= /usr/lib64
|
||||
endif
|
||||
ifeq ("$(RHEL)","0")
|
||||
GLPATH ?= /usr/lib64/nvidia
|
||||
GLLINK ?= -L/usr/lib64/nvidia
|
||||
DFLT_PATH ?= /usr/lib64
|
||||
endif
|
||||
ifeq ("$(CENTOS)","0")
|
||||
GLPATH ?= /usr/lib64/nvidia
|
||||
GLLINK ?= -L/usr/lib64/nvidia
|
||||
DFLT_PATH ?= /usr/lib64
|
||||
endif
|
||||
|
||||
# find libGL, libGLU
|
||||
GLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libGL.so -print 2>/dev/null)
|
||||
GLULIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libGLU.so -print 2>/dev/null)
|
||||
|
||||
ifeq ("$(GLLIB)","")
|
||||
$(info >>> WARNING - libGL.so not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
ifeq ("$(GLULIB)","")
|
||||
$(info >>> WARNING - libGLU.so not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
|
||||
HEADER_SEARCH_PATH ?= $(TARGET_FS)/usr/include
|
||||
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
|
||||
HEADER_SEARCH_PATH += /usr/arm-linux-gnueabihf/include
|
||||
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-aarch64-linux)
|
||||
HEADER_SEARCH_PATH += /usr/aarch64-linux-gnu/include
|
||||
endif
|
||||
|
||||
GLHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name gl.h -print 2>/dev/null)
|
||||
GLUHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name glu.h -print 2>/dev/null)
|
||||
|
||||
ifeq ("$(GLHEADER)","")
|
||||
$(info >>> WARNING - gl.h not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
ifeq ("$(GLUHEADER)","")
|
||||
$(info >>> WARNING - glu.h not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
else
|
||||
# This would be the Mac OS X path if we had to do anything special
|
||||
endif
|
||||
|
||||
355
Samples/smokeParticles/framebufferObject.cpp
Normal file
355
Samples/smokeParticles/framebufferObject.cpp
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Copyright (c) 2005,
|
||||
Aaron Lefohn (lefohn@cs.ucdavis.edu)
|
||||
Robert Strzodka (strzodka@stanford.edu)
|
||||
Adam Moerschell (atmoerschell@ucdavis.edu)
|
||||
All rights reserved.
|
||||
|
||||
This software is licensed under the BSD open-source license. See
|
||||
http://www.opensource.org/licenses/bsd-license.php for more detail.
|
||||
|
||||
*************************************************************
|
||||
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 the University of California, Davis nor the names of
|
||||
the 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 AND CONTRIBUTORS
|
||||
"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.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include "framebufferObject.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
FramebufferObject::FramebufferObject()
|
||||
: m_fboId(_GenerateFboId()), m_savedFboId(0) {
|
||||
// Bind this FBO so that it actually gets created now
|
||||
_GuardedBind();
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
FramebufferObject::~FramebufferObject() {
|
||||
glDeleteFramebuffersEXT(1, &m_fboId);
|
||||
}
|
||||
|
||||
void FramebufferObject::Bind() {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
|
||||
}
|
||||
|
||||
void FramebufferObject::Disable() {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachTexture(GLenum texTarget, GLuint texId,
|
||||
GLenum attachment, int mipLevel,
|
||||
int zSlice) {
|
||||
_GuardedBind();
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
if( GetAttachedId(attachment) != texId ) {
|
||||
#endif
|
||||
*/
|
||||
|
||||
_FramebufferTextureND(attachment, texTarget, texId, mipLevel, zSlice);
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
else {
|
||||
cerr << "FramebufferObject::AttachTexture PERFORMANCE WARNING:\n"
|
||||
<< "\tRedundant bind of texture (id = " << texId << ").\n"
|
||||
<< "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachTextures(int numTextures, GLenum texTarget[],
|
||||
GLuint texId[], GLenum attachment[],
|
||||
int mipLevel[], int zSlice[]) {
|
||||
for (int i = 0; i < numTextures; ++i) {
|
||||
AttachTexture(texTarget[i], texId[i],
|
||||
attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
|
||||
mipLevel ? mipLevel[i] : 0, zSlice ? zSlice[i] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachRenderBuffer(GLuint buffId, GLenum attachment) {
|
||||
_GuardedBind();
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
if (GetAttachedId(attachment) != buffId) {
|
||||
#endif
|
||||
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_RENDERBUFFER_EXT, buffId);
|
||||
|
||||
#ifndef NDEBUG
|
||||
} else {
|
||||
cerr << "FramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n"
|
||||
<< "\tRedundant bind of Renderbuffer (id = " << buffId << ")\n"
|
||||
<< "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachRenderBuffers(int numBuffers, GLuint buffId[],
|
||||
GLenum attachment[]) {
|
||||
for (int i = 0; i < numBuffers; ++i) {
|
||||
AttachRenderBuffer(
|
||||
buffId[i], attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i));
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferObject::Unattach(GLenum attachment) {
|
||||
_GuardedBind();
|
||||
GLenum type = GetAttachedType(attachment);
|
||||
|
||||
switch (type) {
|
||||
case GL_NONE:
|
||||
break;
|
||||
|
||||
case GL_RENDERBUFFER_EXT:
|
||||
AttachRenderBuffer(0, attachment);
|
||||
break;
|
||||
|
||||
case GL_TEXTURE:
|
||||
AttachTexture(GL_TEXTURE_2D, 0, attachment);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << "FramebufferObject::unbind_attachment ERROR: Unknown attached "
|
||||
"resource type\n";
|
||||
}
|
||||
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void FramebufferObject::UnattachAll() {
|
||||
int numAttachments = GetMaxColorAttachments();
|
||||
|
||||
for (int i = 0; i < numAttachments; ++i) {
|
||||
Unattach(GL_COLOR_ATTACHMENT0_EXT + i);
|
||||
}
|
||||
}
|
||||
|
||||
int FramebufferObject::GetMaxColorAttachments() {
|
||||
GLint maxAttach = 0;
|
||||
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach);
|
||||
return maxAttach;
|
||||
}
|
||||
|
||||
GLuint FramebufferObject::_GenerateFboId() {
|
||||
GLuint id = 0;
|
||||
glGenFramebuffersEXT(1, &id);
|
||||
return id;
|
||||
}
|
||||
|
||||
void FramebufferObject::_GuardedBind() {
|
||||
// Only binds if m_fboId is different than the currently bound FBO
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId);
|
||||
|
||||
if (m_fboId != (GLuint)m_savedFboId) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferObject::_GuardedUnbind() {
|
||||
// Returns FBO binding to the previously enabled FBO
|
||||
if (m_fboId != (GLuint)m_savedFboId) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)m_savedFboId);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferObject::_FramebufferTextureND(GLenum attachment,
|
||||
GLenum texTarget, GLuint texId,
|
||||
int mipLevel, int zSlice) {
|
||||
if (texTarget == GL_TEXTURE_1D) {
|
||||
glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_1D,
|
||||
texId, mipLevel);
|
||||
} else if (texTarget == GL_TEXTURE_3D) {
|
||||
glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_3D,
|
||||
texId, mipLevel, zSlice);
|
||||
} else {
|
||||
// Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, texTarget, texId,
|
||||
mipLevel);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool FramebufferObject::IsValid(ostream &ostr) {
|
||||
_GuardedBind();
|
||||
|
||||
bool isOK = false;
|
||||
|
||||
GLenum status;
|
||||
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
|
||||
isOK = true;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "Unknown ERROR\n";
|
||||
isOK = false;
|
||||
}
|
||||
|
||||
_GuardedUnbind();
|
||||
return isOK;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
/// Accessors
|
||||
GLenum FramebufferObject::GetAttachedType(GLenum attachment) {
|
||||
// Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
|
||||
_GuardedBind();
|
||||
GLint type = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(
|
||||
GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
|
||||
&type);
|
||||
_GuardedUnbind();
|
||||
return GLenum(type);
|
||||
}
|
||||
|
||||
GLuint FramebufferObject::GetAttachedId(GLenum attachment) {
|
||||
_GuardedBind();
|
||||
GLint id = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(
|
||||
GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
|
||||
&id);
|
||||
_GuardedUnbind();
|
||||
return GLuint(id);
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedMipLevel(GLenum attachment) {
|
||||
_GuardedBind();
|
||||
GLint level = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(
|
||||
GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &level);
|
||||
_GuardedUnbind();
|
||||
return level;
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedCubeFace(GLenum attachment) {
|
||||
_GuardedBind();
|
||||
GLint level = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(
|
||||
GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT, &level);
|
||||
_GuardedUnbind();
|
||||
return level;
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedZSlice(GLenum attachment) {
|
||||
_GuardedBind();
|
||||
GLint slice = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(
|
||||
GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT, &slice);
|
||||
_GuardedUnbind();
|
||||
return slice;
|
||||
}
|
||||
226
Samples/smokeParticles/framebufferObject.h
Normal file
226
Samples/smokeParticles/framebufferObject.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
Copyright (c) 2005,
|
||||
Aaron Lefohn (lefohn@cs.ucdavis.edu)
|
||||
Robert Strzodka (strzodka@stanford.edu)
|
||||
Adam Moerschell (atmoerschell@ucdavis.edu)
|
||||
All rights reserved.
|
||||
|
||||
This software is licensed under the BSD open-source license. See
|
||||
http://www.opensource.org/licenses/bsd-license.php for more detail.
|
||||
|
||||
*************************************************************
|
||||
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 the University of California, Davis nor the names of
|
||||
the 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 AND CONTRIBUTORS
|
||||
"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.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#ifndef UCDAVIS_FRAMEBUFFER_OBJECT_H
|
||||
#define UCDAVIS_FRAMEBUFFER_OBJECT_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/*!
|
||||
FramebufferObject Class. This class encapsulates the FramebufferObject
|
||||
(FBO) OpenGL spec. See the official spec at:
|
||||
http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
|
||||
|
||||
for details.
|
||||
|
||||
A framebuffer object (FBO) is conceptually a structure containing pointers
|
||||
to GPU memory. The memory pointed to is either an OpenGL texture or an
|
||||
OpenGL RenderBuffer. FBOs can be used to render to one or more textures,
|
||||
share depth buffers between multiple sets of color buffers/textures and
|
||||
are a complete replacement for pbuffers.
|
||||
|
||||
Performance Notes:
|
||||
1) It is more efficient (but not required) to call Bind()
|
||||
on an FBO before making multiple method calls. For example:
|
||||
|
||||
FramebufferObject fbo;
|
||||
fbo.Bind();
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
|
||||
fbo.IsValid();
|
||||
|
||||
To provide a complete encapsulation, the following usage
|
||||
pattern works correctly but is less efficient:
|
||||
|
||||
FramebufferObject fbo;
|
||||
// NOTE : No Bind() call
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
|
||||
fbo.IsValid();
|
||||
|
||||
The first usage pattern binds the FBO only once, whereas
|
||||
the second usage binds/unbinds the FBO for each method call.
|
||||
|
||||
2) Use FramebufferObject::Disable() sparingly. We have intentionally
|
||||
left out an "Unbind()" method because it is largely unnecessary
|
||||
and encourages rendundant Bind/Unbind coding. Binding an FBO is
|
||||
usually much faster than enabling/disabling a pbuffer, but is
|
||||
still a costly operation. When switching between multiple FBOs
|
||||
and a visible OpenGL framebuffer, the following usage pattern
|
||||
is recommended:
|
||||
|
||||
FramebufferObject fbo1, fbo2;
|
||||
fbo1.Bind();
|
||||
... Render ...
|
||||
// NOTE : No Unbind/Disable here...
|
||||
|
||||
fbo2.Bind();
|
||||
... Render ...
|
||||
|
||||
// Disable FBO rendering and return to visible window
|
||||
// OpenGL framebuffer.
|
||||
FramebufferObject::Disable();
|
||||
*/
|
||||
class FramebufferObject {
|
||||
public:
|
||||
/// Ctor/Dtor
|
||||
FramebufferObject();
|
||||
virtual ~FramebufferObject();
|
||||
|
||||
/// Bind this FBO as current render target
|
||||
void Bind();
|
||||
|
||||
/// Bind a texture to the "attachment" point of this FBO
|
||||
virtual void AttachTexture(GLenum texTarget, GLuint texId,
|
||||
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT,
|
||||
int mipLevel = 0, int zSlice = 0);
|
||||
|
||||
/// Bind an array of textures to multiple "attachment" points of this FBO
|
||||
/// - By default, the first 'numTextures' attachments are used,
|
||||
/// starting with GL_COLOR_ATTACHMENT0_EXT
|
||||
virtual void AttachTextures(int numTextures, GLenum texTarget[],
|
||||
GLuint texId[], GLenum attachment[] = NULL,
|
||||
int mipLevel[] = NULL, int zSlice[] = NULL);
|
||||
|
||||
/// Bind a render buffer to the "attachment" point of this FBO
|
||||
virtual void AttachRenderBuffer(GLuint buffId,
|
||||
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT);
|
||||
|
||||
/// Bind an array of render buffers to corresponding "attachment" points
|
||||
/// of this FBO.
|
||||
/// - By default, the first 'numBuffers' attachments are used,
|
||||
/// starting with GL_COLOR_ATTACHMENT0_EXT
|
||||
virtual void AttachRenderBuffers(int numBuffers, GLuint buffId[],
|
||||
GLenum attachment[] = NULL);
|
||||
|
||||
/// Free any resource bound to the "attachment" point of this FBO
|
||||
void Unattach(GLenum attachment);
|
||||
|
||||
/// Free any resources bound to any attachment points of this FBO
|
||||
void UnattachAll();
|
||||
|
||||
/// Is this FBO currently a valid render target?
|
||||
/// - Sends output to std::cerr by default but can
|
||||
/// be a user-defined C++ stream
|
||||
///
|
||||
/// NOTE : This function works correctly in debug build
|
||||
/// mode but always returns "true" if NDEBUG is
|
||||
/// is defined (optimized builds)
|
||||
#ifndef NDEBUG
|
||||
bool IsValid(std::ostream &ostr = std::cerr);
|
||||
#else
|
||||
bool IsValid(std::ostream &ostr = std::cerr) { return true; }
|
||||
#endif
|
||||
|
||||
/// BEGIN : Accessors
|
||||
/// Is attached type GL_RENDERBUFFER_EXT or GL_TEXTURE?
|
||||
GLenum GetAttachedType(GLenum attachment);
|
||||
|
||||
/// What is the Id of Renderbuffer/texture currently
|
||||
/// attached to "attachment?"
|
||||
GLuint GetAttachedId(GLenum attachment);
|
||||
|
||||
/// Which mipmap level is currently attached to "attachment?"
|
||||
GLint GetAttachedMipLevel(GLenum attachment);
|
||||
|
||||
/// Which cube face is currently attached to "attachment?"
|
||||
GLint GetAttachedCubeFace(GLenum attachment);
|
||||
|
||||
/// Which z-slice is currently attached to "attachment?"
|
||||
GLint GetAttachedZSlice(GLenum attachment);
|
||||
/// END : Accessors
|
||||
|
||||
/// BEGIN : Static methods global to all FBOs
|
||||
/// Return number of color attachments permitted
|
||||
static int GetMaxColorAttachments();
|
||||
|
||||
/// Disable all FBO rendering and return to traditional,
|
||||
/// windowing-system controlled framebuffer
|
||||
/// NOTE:
|
||||
/// This is NOT an "unbind" for this specific FBO, but rather
|
||||
/// disables all FBO rendering. This call is intentionally "static"
|
||||
/// and named "Disable" instead of "Unbind" for this reason. The
|
||||
/// motivation for this strange semantic is performance. Providing
|
||||
/// "Unbind" would likely lead to a large number of unnecessary
|
||||
/// FBO enabling/disabling.
|
||||
static void Disable();
|
||||
/// END : Static methods global to all FBOs
|
||||
|
||||
protected:
|
||||
void _GuardedBind();
|
||||
void _GuardedUnbind();
|
||||
void _FramebufferTextureND(GLenum attachment, GLenum texTarget, GLuint texId,
|
||||
int mipLevel, int zSlice);
|
||||
static GLuint _GenerateFboId();
|
||||
|
||||
private:
|
||||
GLuint m_fboId;
|
||||
GLint m_savedFboId;
|
||||
};
|
||||
|
||||
#endif
|
||||
89
Samples/smokeParticles/nvMath.h
Normal file
89
Samples/smokeParticles/nvMath.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Template math library for common 3D functionality
|
||||
//
|
||||
// This code is in part deriver from glh, a cross platform glut helper library.
|
||||
// The copyright for glh follows this notice.
|
||||
//
|
||||
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2000 Cass Everitt
|
||||
Copyright (c) 2000 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.
|
||||
|
||||
* The names of contributors to this software may not be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``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
|
||||
REGENTS 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.
|
||||
|
||||
|
||||
Cass Everitt - cass@r3.nu
|
||||
*/
|
||||
|
||||
#ifndef NV_MATH_H
|
||||
#define NV_MATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <nvVector.h>
|
||||
#include <nvMatrix.h>
|
||||
#include <nvQuaternion.h>
|
||||
|
||||
#define NV_PI float(3.1415926535897932384626433832795)
|
||||
|
||||
namespace nv {
|
||||
|
||||
typedef vec2<float> vec2f;
|
||||
typedef vec3<float> vec3f;
|
||||
typedef vec3<int> vec3i;
|
||||
typedef vec3<unsigned int> vec3ui;
|
||||
typedef vec4<float> vec4f;
|
||||
typedef matrix4<float> matrix4f;
|
||||
typedef quaternion<float> quaternionf;
|
||||
|
||||
inline void applyRotation(const quaternionf &r) {
|
||||
float angle;
|
||||
vec3f axis;
|
||||
r.get_value(axis, angle);
|
||||
glRotatef(angle / 3.1415926f * 180.0f, axis[0], axis[1], axis[2]);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
446
Samples/smokeParticles/nvMatrix.h
Normal file
446
Samples/smokeParticles/nvMatrix.h
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Template math library for common 3D functionality
|
||||
//
|
||||
// nvMatrix.h - template matrix code
|
||||
//
|
||||
// This code is in part deriver from glh, a cross platform glut helper library.
|
||||
// The copyright for glh follows this notice.
|
||||
//
|
||||
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2000 Cass Everitt
|
||||
Copyright (c) 2000 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.
|
||||
|
||||
* The names of contributors to this software may not be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``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
|
||||
REGENTS 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.
|
||||
|
||||
|
||||
Cass Everitt - cass@r3.nu
|
||||
*/
|
||||
|
||||
#ifndef NV_MATRIX_H
|
||||
#define NV_MATRIX_H
|
||||
|
||||
namespace nv {
|
||||
|
||||
template <class T>
|
||||
class vec2;
|
||||
template <class T>
|
||||
class vec3;
|
||||
template <class T>
|
||||
class vec4;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Matrix
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class matrix4 {
|
||||
public:
|
||||
matrix4() { make_identity(); }
|
||||
|
||||
matrix4(T t) { set_value(t); }
|
||||
|
||||
matrix4(const T *m) { set_value(m); }
|
||||
|
||||
matrix4(T a00, T a01, T a02, T a03, T a10, T a11, T a12, T a13, T a20, T a21,
|
||||
T a22, T a23, T a30, T a31, T a32, T a33)
|
||||
: _11(a00),
|
||||
_12(a01),
|
||||
_13(a02),
|
||||
_14(a03),
|
||||
_21(a10),
|
||||
_22(a11),
|
||||
_23(a12),
|
||||
_24(a13),
|
||||
_31(a20),
|
||||
_32(a21),
|
||||
_33(a22),
|
||||
_34(a23),
|
||||
_41(a30),
|
||||
_42(a31),
|
||||
_43(a32),
|
||||
_44(a33) {}
|
||||
|
||||
void get_value(T *mp) const {
|
||||
int c = 0;
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mp[c++] = element(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
const T *get_value() const { return _array; }
|
||||
|
||||
void set_value(T *mp) {
|
||||
int c = 0;
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
element(i, j) = mp[c++];
|
||||
}
|
||||
}
|
||||
|
||||
void set_value(T r) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++) {
|
||||
element(i, j) = r;
|
||||
}
|
||||
}
|
||||
|
||||
void make_identity() {
|
||||
element(0, 0) = 1.0;
|
||||
element(0, 1) = 0.0;
|
||||
element(0, 2) = 0.0;
|
||||
element(0, 3) = 0.0;
|
||||
|
||||
element(1, 0) = 0.0;
|
||||
element(1, 1) = 1.0;
|
||||
element(1, 2) = 0.0;
|
||||
element(1, 3) = 0.0;
|
||||
|
||||
element(2, 0) = 0.0;
|
||||
element(2, 1) = 0.0;
|
||||
element(2, 2) = 1.0;
|
||||
element(2, 3) = 0.0;
|
||||
|
||||
element(3, 0) = 0.0;
|
||||
element(3, 1) = 0.0;
|
||||
element(3, 2) = 0.0;
|
||||
element(3, 3) = 1.0;
|
||||
}
|
||||
|
||||
// set a uniform scale
|
||||
void set_scale(T s) {
|
||||
element(0, 0) = s;
|
||||
element(1, 1) = s;
|
||||
element(2, 2) = s;
|
||||
}
|
||||
|
||||
void set_scale(const vec3<T> &s) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
element(i, i) = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
void set_translate(const vec3<T> &t) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
element(i, 3) = t[i];
|
||||
}
|
||||
}
|
||||
|
||||
void set_row(int r, const vec4<T> &t) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
element(r, i) = t[i];
|
||||
}
|
||||
}
|
||||
|
||||
void set_column(int c, const vec4<T> &t) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
element(i, c) = t[i];
|
||||
}
|
||||
}
|
||||
|
||||
vec4<T> get_row(int r) const {
|
||||
vec4<T> v;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
v[i] = element(r, i);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
vec4<T> get_column(int c) const {
|
||||
vec4<T> v;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
v[i] = element(i, c);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
friend matrix4 inverse(const matrix4 &m) {
|
||||
matrix4 minv;
|
||||
|
||||
T r1[8], r2[8], r3[8], r4[8];
|
||||
T *s[4], *tmprow;
|
||||
|
||||
s[0] = &r1[0];
|
||||
s[1] = &r2[0];
|
||||
s[2] = &r3[0];
|
||||
s[3] = &r4[0];
|
||||
|
||||
register int i, j, p, jj;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
s[i][j] = m.element(i, j);
|
||||
|
||||
if (i == j) {
|
||||
s[i][j + 4] = 1.0;
|
||||
} else {
|
||||
s[i][j + 4] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T scp[4];
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
scp[i] = T(fabs(s[i][0]));
|
||||
|
||||
for (j = 1; j < 4; j++)
|
||||
if (T(fabs(s[i][j])) > scp[i]) {
|
||||
scp[i] = T(fabs(s[i][j]));
|
||||
}
|
||||
|
||||
if (scp[i] == 0.0) {
|
||||
return minv; // singular matrix!
|
||||
}
|
||||
}
|
||||
|
||||
int pivot_to;
|
||||
T scp_max;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
// select pivot row
|
||||
pivot_to = i;
|
||||
scp_max = T(fabs(s[i][i] / scp[i]));
|
||||
|
||||
// find out which row should be on top
|
||||
for (p = i + 1; p < 4; p++)
|
||||
if (T(fabs(s[p][i] / scp[p])) > scp_max) {
|
||||
scp_max = T(fabs(s[p][i] / scp[p]));
|
||||
pivot_to = p;
|
||||
}
|
||||
|
||||
// Pivot if necessary
|
||||
if (pivot_to != i) {
|
||||
tmprow = s[i];
|
||||
s[i] = s[pivot_to];
|
||||
s[pivot_to] = tmprow;
|
||||
T tmpscp;
|
||||
tmpscp = scp[i];
|
||||
scp[i] = scp[pivot_to];
|
||||
scp[pivot_to] = tmpscp;
|
||||
}
|
||||
|
||||
T mji;
|
||||
|
||||
// perform gaussian elimination
|
||||
for (j = i + 1; j < 4; j++) {
|
||||
mji = s[j][i] / s[i][i];
|
||||
s[j][i] = 0.0;
|
||||
|
||||
for (jj = i + 1; jj < 8; jj++) {
|
||||
s[j][jj] -= mji * s[i][jj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s[3][3] == 0.0) {
|
||||
return minv; // singular matrix!
|
||||
}
|
||||
|
||||
//
|
||||
// Now we have an upper triangular matrix.
|
||||
//
|
||||
// x x x x | y y y y
|
||||
// 0 x x x | y y y y
|
||||
// 0 0 x x | y y y y
|
||||
// 0 0 0 x | y y y y
|
||||
//
|
||||
// we'll back substitute to get the inverse
|
||||
//
|
||||
// 1 0 0 0 | z z z z
|
||||
// 0 1 0 0 | z z z z
|
||||
// 0 0 1 0 | z z z z
|
||||
// 0 0 0 1 | z z z z
|
||||
//
|
||||
|
||||
T mij;
|
||||
|
||||
for (i = 3; i > 0; i--) {
|
||||
for (j = i - 1; j > -1; j--) {
|
||||
mij = s[j][i] / s[i][i];
|
||||
|
||||
for (jj = j + 1; jj < 8; jj++) {
|
||||
s[j][jj] -= mij * s[i][jj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 4; j++) {
|
||||
minv(i, j) = s[i][j + 4] / s[i][i];
|
||||
}
|
||||
|
||||
return minv;
|
||||
}
|
||||
|
||||
friend matrix4 transpose(const matrix4 &m) {
|
||||
matrix4 mtrans;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++) {
|
||||
mtrans(i, j) = m.element(j, i);
|
||||
}
|
||||
|
||||
return mtrans;
|
||||
}
|
||||
|
||||
matrix4 &operator*=(const matrix4 &rhs) {
|
||||
matrix4 mt(*this);
|
||||
set_value(T(0));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
for (int c = 0; c < 4; c++) {
|
||||
element(i, j) += mt(i, c) * rhs(c, j);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend matrix4 operator*(const matrix4 &lhs, const matrix4 &rhs) {
|
||||
matrix4 r(T(0));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
for (int c = 0; c < 4; c++) {
|
||||
r.element(i, j) += lhs(i, c) * rhs(c, j);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// dst = M * src
|
||||
vec4<T> operator*(const vec4<T> &src) const {
|
||||
vec4<T> r;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
r[i] = (src[0] * element(i, 0) + src[1] * element(i, 1) +
|
||||
src[2] * element(i, 2) + src[3] * element(i, 3));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// dst = src * M
|
||||
friend vec4<T> operator*(const vec4<T> &lhs, const matrix4 &rhs) {
|
||||
vec4<T> r;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
r[i] = (lhs[0] * rhs.element(0, i) + lhs[1] * rhs.element(1, i) +
|
||||
lhs[2] * rhs.element(2, i) + lhs[3] * rhs.element(3, i));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
T &operator()(int row, int col) { return element(row, col); }
|
||||
|
||||
const T &operator()(int row, int col) const { return element(row, col); }
|
||||
|
||||
T &element(int row, int col) { return _array[row | (col << 2)]; }
|
||||
|
||||
const T &element(int row, int col) const { return _array[row | (col << 2)]; }
|
||||
|
||||
matrix4 &operator*=(const T &r) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
element(0, i) *= r;
|
||||
element(1, i) *= r;
|
||||
element(2, i) *= r;
|
||||
element(3, i) *= r;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
matrix4 &operator+=(const matrix4 &mat) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
element(0, i) += mat.element(0, i);
|
||||
element(1, i) += mat.element(1, i);
|
||||
element(2, i) += mat.element(2, i);
|
||||
element(3, i) += mat.element(3, i);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const matrix4 &lhs, const matrix4 &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
friend bool operator!=(const matrix4 &lhs, const matrix4 &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
r &= lhs._array[i] != rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
T _11, _12, _13, _14; // standard names for components
|
||||
T _21, _22, _23, _24; // standard names for components
|
||||
T _31, _32, _33, _34; // standard names for components
|
||||
T _41, _42, _43, _44; // standard names for components
|
||||
};
|
||||
T _array[16]; // array access
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
438
Samples/smokeParticles/nvQuaternion.h
Normal file
438
Samples/smokeParticles/nvQuaternion.h
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Template math library for common 3D functionality
|
||||
//
|
||||
// nvQuaterion.h - quaternion template and utility functions
|
||||
//
|
||||
// This code is in part deriver from glh, a cross platform glut helper library.
|
||||
// The copyright for glh follows this notice.
|
||||
//
|
||||
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2000 Cass Everitt
|
||||
Copyright (c) 2000 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.
|
||||
|
||||
* The names of contributors to this software may not be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``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
|
||||
REGENTS 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.
|
||||
|
||||
|
||||
Cass Everitt - cass@r3.nu
|
||||
*/
|
||||
#ifndef NV_QUATERNION_H
|
||||
#define NV_QUATERNION_H
|
||||
|
||||
namespace nv {
|
||||
|
||||
template <class T>
|
||||
class vec2;
|
||||
template <class T>
|
||||
class vec3;
|
||||
template <class T>
|
||||
class vec4;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Quaternion
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class quaternion {
|
||||
public:
|
||||
quaternion() : x(0.0), y(0.0), z(0.0), w(0.0) {}
|
||||
|
||||
quaternion(const T v[4]) { set_value(v); }
|
||||
|
||||
quaternion(T q0, T q1, T q2, T q3) { set_value(q0, q1, q2, q3); }
|
||||
|
||||
quaternion(const matrix4<T> &m) { set_value(m); }
|
||||
|
||||
quaternion(const vec3<T> &axis, T radians) { set_value(axis, radians); }
|
||||
|
||||
quaternion(const vec3<T> &rotateFrom, const vec3<T> &rotateTo) {
|
||||
set_value(rotateFrom, rotateTo);
|
||||
}
|
||||
|
||||
quaternion(const vec3<T> &from_look, const vec3<T> &from_up,
|
||||
const vec3<T> &to_look, const vec3<T> &to_up) {
|
||||
set_value(from_look, from_up, to_look, to_up);
|
||||
}
|
||||
|
||||
const T *get_value() const { return &_array[0]; }
|
||||
|
||||
void get_value(T &q0, T &q1, T &q2, T &q3) const {
|
||||
q0 = _array[0];
|
||||
q1 = _array[1];
|
||||
q2 = _array[2];
|
||||
q3 = _array[3];
|
||||
}
|
||||
|
||||
quaternion &set_value(T q0, T q1, T q2, T q3) {
|
||||
_array[0] = q0;
|
||||
_array[1] = q1;
|
||||
_array[2] = q2;
|
||||
_array[3] = q3;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void get_value(vec3<T> &axis, T &radians) const {
|
||||
radians = T(acos(_array[3]) * T(2.0));
|
||||
|
||||
if (radians == T(0.0)) {
|
||||
axis = vec3<T>(0.0, 0.0, 1.0);
|
||||
} else {
|
||||
axis[0] = _array[0];
|
||||
axis[1] = _array[1];
|
||||
axis[2] = _array[2];
|
||||
axis = normalize(axis);
|
||||
}
|
||||
}
|
||||
|
||||
void get_value(matrix4<T> &m) const {
|
||||
T s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
|
||||
|
||||
T norm = _array[0] * _array[0] + _array[1] * _array[1] +
|
||||
_array[2] * _array[2] + _array[3] * _array[3];
|
||||
|
||||
s = (norm == T(0.0)) ? T(0.0) : (T(2.0) / norm);
|
||||
|
||||
xs = _array[0] * s;
|
||||
ys = _array[1] * s;
|
||||
zs = _array[2] * s;
|
||||
|
||||
wx = _array[3] * xs;
|
||||
wy = _array[3] * ys;
|
||||
wz = _array[3] * zs;
|
||||
|
||||
xx = _array[0] * xs;
|
||||
xy = _array[0] * ys;
|
||||
xz = _array[0] * zs;
|
||||
|
||||
yy = _array[1] * ys;
|
||||
yz = _array[1] * zs;
|
||||
zz = _array[2] * zs;
|
||||
|
||||
m(0, 0) = T(T(1.0) - (yy + zz));
|
||||
m(1, 0) = T(xy + wz);
|
||||
m(2, 0) = T(xz - wy);
|
||||
|
||||
m(0, 1) = T(xy - wz);
|
||||
m(1, 1) = T(T(1.0) - (xx + zz));
|
||||
m(2, 1) = T(yz + wx);
|
||||
|
||||
m(0, 2) = T(xz + wy);
|
||||
m(1, 2) = T(yz - wx);
|
||||
m(2, 2) = T(T(1.0) - (xx + yy));
|
||||
|
||||
m(3, 0) = m(3, 1) = m(3, 2) = m(0, 3) = m(1, 3) = m(2, 3) = T(0.0);
|
||||
m(3, 3) = T(1.0);
|
||||
}
|
||||
|
||||
quaternion &set_value(const T *qp) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_array[i] = qp[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
quaternion &set_value(const matrix4<T> &m) {
|
||||
T tr, s;
|
||||
int i, j, k;
|
||||
const int nxt[3] = {1, 2, 0};
|
||||
|
||||
tr = m(0, 0) + m(1, 1) + m(2, 2);
|
||||
|
||||
if (tr > T(0)) {
|
||||
s = T(sqrt(tr + m(3, 3)));
|
||||
_array[3] = T(s * 0.5);
|
||||
s = T(0.5) / s;
|
||||
|
||||
_array[0] = T((m(1, 2) - m(2, 1)) * s);
|
||||
_array[1] = T((m(2, 0) - m(0, 2)) * s);
|
||||
_array[2] = T((m(0, 1) - m(1, 0)) * s);
|
||||
} else {
|
||||
i = 0;
|
||||
|
||||
if (m(1, 1) > m(0, 0)) {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
if (m(2, 2) > m(i, i)) {
|
||||
i = 2;
|
||||
}
|
||||
|
||||
j = nxt[i];
|
||||
k = nxt[j];
|
||||
|
||||
s = T(sqrt((m(i, j) - (m(j, j) + m(k, k))) + T(1.0)));
|
||||
|
||||
_array[i] = T(s * 0.5);
|
||||
s = T(0.5 / s);
|
||||
|
||||
_array[3] = T((m(j, k) - m(k, j)) * s);
|
||||
_array[j] = T((m(i, j) + m(j, i)) * s);
|
||||
_array[k] = T((m(i, k) + m(k, i)) * s);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
quaternion &set_value(const vec3<T> &axis, T theta) {
|
||||
T sqnorm = square_norm(axis);
|
||||
|
||||
if (sqnorm == T(0.0)) {
|
||||
// axis too small.
|
||||
x = y = z = T(0.0);
|
||||
w = T(1.0);
|
||||
} else {
|
||||
theta *= T(0.5);
|
||||
T sin_theta = T(sin(theta));
|
||||
|
||||
if (sqnorm != T(1)) {
|
||||
sin_theta /= T(sqrt(sqnorm));
|
||||
}
|
||||
|
||||
x = sin_theta * axis[0];
|
||||
y = sin_theta * axis[1];
|
||||
z = sin_theta * axis[2];
|
||||
w = T(cos(theta));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
quaternion &set_value(const vec3<T> &rotateFrom, const vec3<T> &rotateTo) {
|
||||
vec3<T> p1, p2;
|
||||
T alpha;
|
||||
|
||||
p1 = normalize(rotateFrom);
|
||||
p2 = normalize(rotateTo);
|
||||
|
||||
alpha = dot(p1, p2);
|
||||
|
||||
if (alpha == T(1.0)) {
|
||||
*this = quaternion();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ensures that the anti-parallel case leads to a positive dot
|
||||
if (alpha == T(-1.0)) {
|
||||
vec3<T> v;
|
||||
|
||||
if (p1[0] != p1[1] || p1[0] != p1[2]) {
|
||||
v = vec3<T>(p1[1], p1[2], p1[0]);
|
||||
} else {
|
||||
v = vec3<T>(-p1[0], p1[1], p1[2]);
|
||||
}
|
||||
|
||||
v -= p1 * dot(p1, v);
|
||||
v = normalize(v);
|
||||
|
||||
set_value(v, T(3.1415926));
|
||||
return *this;
|
||||
}
|
||||
|
||||
p1 = normalize(cross(p1, p2));
|
||||
|
||||
set_value(p1, T(acos(alpha)));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
quaternion &set_value(const vec3<T> &from_look, const vec3<T> &from_up,
|
||||
const vec3<T> &to_look, const vec3<T> &to_up) {
|
||||
quaternion r_look = quaternion(from_look, to_look);
|
||||
|
||||
vec3<T> rotated_from_up(from_up);
|
||||
r_look.mult_vec(rotated_from_up);
|
||||
|
||||
quaternion r_twist = quaternion(rotated_from_up, to_up);
|
||||
|
||||
*this = r_twist;
|
||||
*this *= r_look;
|
||||
return *this;
|
||||
}
|
||||
|
||||
quaternion &operator*=(const quaternion<T> &qr) {
|
||||
quaternion ql(*this);
|
||||
|
||||
w = ql.w * qr.w - ql.x * qr.x - ql.y * qr.y - ql.z * qr.z;
|
||||
x = ql.w * qr.x + ql.x * qr.w + ql.y * qr.z - ql.z * qr.y;
|
||||
y = ql.w * qr.y + ql.y * qr.w + ql.z * qr.x - ql.x * qr.z;
|
||||
z = ql.w * qr.z + ql.z * qr.w + ql.x * qr.y - ql.y * qr.x;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend quaternion normalize(const quaternion<T> &q) {
|
||||
quaternion r(q);
|
||||
T rnorm = T(1.0) / T(sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z));
|
||||
|
||||
r.x *= rnorm;
|
||||
r.y *= rnorm;
|
||||
r.z *= rnorm;
|
||||
r.w *= rnorm;
|
||||
}
|
||||
|
||||
friend quaternion<T> conjugate(const quaternion<T> &q) {
|
||||
quaternion<T> r(q);
|
||||
r._array[0] *= T(-1.0);
|
||||
r._array[1] *= T(-1.0);
|
||||
r._array[2] *= T(-1.0);
|
||||
return r;
|
||||
}
|
||||
|
||||
friend quaternion<T> inverse(const quaternion<T> &q) { return conjugate(q); }
|
||||
|
||||
//
|
||||
// Quaternion multiplication with cartesian vector
|
||||
// v' = q*v*q(star)
|
||||
//
|
||||
void mult_vec(const vec3<T> &src, vec3<T> &dst) const {
|
||||
T v_coef = w * w - x * x - y * y - z * z;
|
||||
T u_coef = T(2.0) * (src[0] * x + src[1] * y + src[2] * z);
|
||||
T c_coef = T(2.0) * w;
|
||||
|
||||
dst.v[0] =
|
||||
v_coef * src.v[0] + u_coef * x + c_coef * (y * src.v[2] - z * src.v[1]);
|
||||
dst.v[1] =
|
||||
v_coef * src.v[1] + u_coef * y + c_coef * (z * src.v[0] - x * src.v[2]);
|
||||
dst.v[2] =
|
||||
v_coef * src.v[2] + u_coef * z + c_coef * (x * src.v[1] - y * src.v[0]);
|
||||
}
|
||||
|
||||
void mult_vec(vec3<T> &src_and_dst) const {
|
||||
mult_vec(vec3<T>(src_and_dst), src_and_dst);
|
||||
}
|
||||
|
||||
void scale_angle(T scaleFactor) {
|
||||
vec3<T> axis;
|
||||
T radians;
|
||||
|
||||
get_value(axis, radians);
|
||||
radians *= scaleFactor;
|
||||
set_value(axis, radians);
|
||||
}
|
||||
|
||||
friend quaternion<T> slerp(const quaternion<T> &p, const quaternion<T> &q,
|
||||
T alpha) {
|
||||
quaternion r;
|
||||
|
||||
T cos_omega = p.x * q.x + p.y * q.y + p.z * q.z + p.w * q.w;
|
||||
// if B is on opposite hemisphere from A, use -B instead
|
||||
|
||||
int bflip;
|
||||
|
||||
if ((bflip = (cos_omega < T(0)))) {
|
||||
cos_omega = -cos_omega;
|
||||
}
|
||||
|
||||
// complementary interpolation parameter
|
||||
T beta = T(1) - alpha;
|
||||
|
||||
if (cos_omega >= T(1)) {
|
||||
return p;
|
||||
}
|
||||
|
||||
T omega = T(acos(cos_omega));
|
||||
T one_over_sin_omega = T(1.0) / T(sin(omega));
|
||||
|
||||
beta = T(sin(omega * beta) * one_over_sin_omega);
|
||||
alpha = T(sin(omega * alpha) * one_over_sin_omega);
|
||||
|
||||
if (bflip) {
|
||||
alpha = -alpha;
|
||||
}
|
||||
|
||||
r.x = beta * p._array[0] + alpha * q._array[0];
|
||||
r.y = beta * p._array[1] + alpha * q._array[1];
|
||||
r.z = beta * p._array[2] + alpha * q._array[2];
|
||||
r.w = beta * p._array[3] + alpha * q._array[3];
|
||||
return r;
|
||||
}
|
||||
|
||||
T &operator[](int i) { return _array[i]; }
|
||||
|
||||
const T &operator[](int i) const { return _array[i]; }
|
||||
|
||||
friend bool operator==(const quaternion<T> &lhs, const quaternion<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
friend bool operator!=(const quaternion<T> &lhs, const quaternion<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
friend quaternion<T> operator*(const quaternion<T> &lhs,
|
||||
const quaternion<T> &rhs) {
|
||||
quaternion r(lhs);
|
||||
r *= rhs;
|
||||
return r;
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
T w;
|
||||
};
|
||||
T _array[4];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
867
Samples/smokeParticles/nvVector.h
Normal file
867
Samples/smokeParticles/nvVector.h
Normal file
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Template math library for common 3D functionality
|
||||
//
|
||||
// nvVector.h - 2-vector, 3-vector, and 4-vector templates and utilities
|
||||
//
|
||||
// This code is in part deriver from glh, a cross platform glut helper library.
|
||||
// The copyright for glh follows this notice.
|
||||
//
|
||||
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2000 Cass Everitt
|
||||
Copyright (c) 2000 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.
|
||||
|
||||
* The names of contributors to this software may not be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``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
|
||||
REGENTS 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.
|
||||
|
||||
|
||||
Cass Everitt - cass@r3.nu
|
||||
*/
|
||||
#ifndef NV_VECTOR_H
|
||||
#define NV_VECTOR_H
|
||||
|
||||
namespace nv {
|
||||
|
||||
template <class T>
|
||||
class vec2;
|
||||
template <class T>
|
||||
class vec3;
|
||||
template <class T>
|
||||
class vec4;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// vec2 - template class for 2-tuple vector
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class vec2 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
int size() const { return 2; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// Default/scalar constructor
|
||||
vec2(const T &t = T()) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from array
|
||||
vec2(const T *tp) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = tp[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from explicit values
|
||||
vec2(const T v0, const T v1) {
|
||||
x = v0;
|
||||
y = v1;
|
||||
}
|
||||
|
||||
explicit vec2(const vec3<T> &u) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = u._array[i];
|
||||
}
|
||||
}
|
||||
|
||||
explicit vec2(const vec4<T> &u) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = u._array[i];
|
||||
}
|
||||
}
|
||||
|
||||
const T *get_value() const { return _array; }
|
||||
|
||||
vec2<T> &set_value(const T *rhs) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = rhs[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// indexing operators
|
||||
T &operator[](int i) { return _array[i]; }
|
||||
|
||||
const T &operator[](int i) const { return _array[i]; }
|
||||
|
||||
// type-cast operators
|
||||
operator T *() { return _array; }
|
||||
|
||||
operator const T *() const { return _array; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Math operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// scalar multiply assign
|
||||
friend vec2<T> &operator*=(vec2<T> &lhs, T d) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector multiply assign
|
||||
friend vec2<T> &operator*=(vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= rhs[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// scalar divide assign
|
||||
friend vec2<T> &operator/=(vec2<T> &lhs, T d) {
|
||||
if (d == 0) {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector divide assign
|
||||
friend vec2<T> &operator/=(vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector add assign
|
||||
friend vec2<T> &operator+=(vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] += rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector subtract assign
|
||||
friend vec2<T> &operator-=(vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] -= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// unary negate
|
||||
friend vec2<T> operator-(const vec2<T> &rhs) {
|
||||
vec2<T> rv;
|
||||
|
||||
for (int i = 0; i < rhs.size(); i++) {
|
||||
rv._array[i] = -rhs._array[i];
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// vector add
|
||||
friend vec2<T> operator+(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt += rhs;
|
||||
}
|
||||
|
||||
// vector subtract
|
||||
friend vec2<T> operator-(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt -= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec2<T> operator*(const vec2<T> &lhs, T rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec2<T> operator*(T lhs, const vec2<T> &rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec2<T> operator*(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec2<T> operator/(const vec2<T> &lhs, T rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec2<T> operator/(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
vec2<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Comparison operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// equality
|
||||
friend bool operator==(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// inequality
|
||||
friend bool operator!=(const vec2<T> &lhs, const vec2<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] != rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// data intentionally left public to allow vec2.x
|
||||
union {
|
||||
struct {
|
||||
T x, y; // standard names for components
|
||||
};
|
||||
struct {
|
||||
T s, t; // standard names for components
|
||||
};
|
||||
T _array[2]; // array access
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// vec3 - template class for 3-tuple vector
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class vec3 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
int size() const { return 3; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// Default/scalar constructor
|
||||
vec3(const T &t = T()) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from array
|
||||
vec3(const T *tp) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = tp[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from explicit values
|
||||
vec3(const T v0, const T v1, const T v2) {
|
||||
x = v0;
|
||||
y = v1;
|
||||
z = v2;
|
||||
}
|
||||
|
||||
explicit vec3(const vec4<T> &u) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = u._array[i];
|
||||
}
|
||||
}
|
||||
|
||||
explicit vec3(const vec2<T> &u, T v0) {
|
||||
x = u.x;
|
||||
y = u.y;
|
||||
z = v0;
|
||||
}
|
||||
|
||||
const T *get_value() const { return _array; }
|
||||
|
||||
vec3<T> &set_value(const T *rhs) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = rhs[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// indexing operators
|
||||
T &operator[](int i) { return _array[i]; }
|
||||
|
||||
const T &operator[](int i) const { return _array[i]; }
|
||||
|
||||
// type-cast operators
|
||||
operator T *() { return _array; }
|
||||
|
||||
operator const T *() const { return _array; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Math operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// scalar multiply assign
|
||||
friend vec3<T> &operator*=(vec3<T> &lhs, T d) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector multiply assign
|
||||
friend vec3<T> &operator*=(vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= rhs[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// scalar divide assign
|
||||
friend vec3<T> &operator/=(vec3<T> &lhs, T d) {
|
||||
if (d == 0) {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector divide assign
|
||||
friend vec3<T> &operator/=(vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector add assign
|
||||
friend vec3<T> &operator+=(vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] += rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector subtract assign
|
||||
friend vec3<T> &operator-=(vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] -= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// unary negate
|
||||
friend vec3<T> operator-(const vec3<T> &rhs) {
|
||||
vec3<T> rv;
|
||||
|
||||
for (int i = 0; i < rhs.size(); i++) {
|
||||
rv._array[i] = -rhs._array[i];
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// vector add
|
||||
friend vec3<T> operator+(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt += rhs;
|
||||
}
|
||||
|
||||
// vector subtract
|
||||
friend vec3<T> operator-(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt -= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec3<T> operator*(const vec3<T> &lhs, T rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec3<T> operator*(T lhs, const vec3<T> &rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec3<T> operator*(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec3<T> operator/(const vec3<T> &lhs, T rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec3<T> operator/(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
vec3<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Comparison operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// equality
|
||||
friend bool operator==(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// inequality
|
||||
friend bool operator!=(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] != rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// dimension specific operations
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// cross product
|
||||
friend vec3<T> cross(const vec3<T> &lhs, const vec3<T> &rhs) {
|
||||
vec3<T> r;
|
||||
|
||||
r.x = lhs.y * rhs.z - lhs.z * rhs.y;
|
||||
r.y = lhs.z * rhs.x - lhs.x * rhs.z;
|
||||
r.z = lhs.x * rhs.y - lhs.y * rhs.x;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// data intentionally left public to allow vec2.x
|
||||
union {
|
||||
struct {
|
||||
T x, y, z; // standard names for components
|
||||
};
|
||||
struct {
|
||||
T s, t, r; // standard names for components
|
||||
};
|
||||
T _array[3]; // array access
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// vec4 - template class for 4-tuple vector
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class vec4 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
int size() const { return 4; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// Default/scalar constructor
|
||||
vec4(const T &t = T()) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from array
|
||||
vec4(const T *tp) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = tp[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from explicit values
|
||||
vec4(const T v0, const T v1, const T v2, const T v3) {
|
||||
x = v0;
|
||||
y = v1;
|
||||
z = v2;
|
||||
w = v3;
|
||||
}
|
||||
|
||||
explicit vec4(const vec3<T> &u, T v0) {
|
||||
x = u.x;
|
||||
y = u.y;
|
||||
z = u.z;
|
||||
w = v0;
|
||||
}
|
||||
|
||||
explicit vec4(const vec2<T> &u, T v0, T v1) {
|
||||
x = u.x;
|
||||
y = u.y;
|
||||
z = v0;
|
||||
w = v1;
|
||||
}
|
||||
|
||||
const T *get_value() const { return _array; }
|
||||
|
||||
vec4<T> &set_value(const T *rhs) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
_array[i] = rhs[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// indexing operators
|
||||
T &operator[](int i) { return _array[i]; }
|
||||
|
||||
const T &operator[](int i) const { return _array[i]; }
|
||||
|
||||
// type-cast operators
|
||||
operator T *() { return _array; }
|
||||
|
||||
operator const T *() const { return _array; }
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Math operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// scalar multiply assign
|
||||
friend vec4<T> &operator*=(vec4<T> &lhs, T d) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector multiply assign
|
||||
friend vec4<T> &operator*=(vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] *= rhs[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// scalar divide assign
|
||||
friend vec4<T> &operator/=(vec4<T> &lhs, T d) {
|
||||
if (d == 0) {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= d;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector divide assign
|
||||
friend vec4<T> &operator/=(vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] /= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector add assign
|
||||
friend vec4<T> &operator+=(vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] += rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// component-wise vector subtract assign
|
||||
friend vec4<T> &operator-=(vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
lhs._array[i] -= rhs._array[i];
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// unary negate
|
||||
friend vec4<T> operator-(const vec4<T> &rhs) {
|
||||
vec4<T> rv;
|
||||
|
||||
for (int i = 0; i < rhs.size(); i++) {
|
||||
rv._array[i] = -rhs._array[i];
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// vector add
|
||||
friend vec4<T> operator+(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt += rhs;
|
||||
}
|
||||
|
||||
// vector subtract
|
||||
friend vec4<T> operator-(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt -= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec4<T> operator*(const vec4<T> &lhs, T rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec4<T> operator*(T lhs, const vec4<T> &rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec4<T> operator*(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt *= rhs;
|
||||
}
|
||||
|
||||
// scalar multiply
|
||||
friend vec4<T> operator/(const vec4<T> &lhs, T rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
// vector component-wise multiply
|
||||
friend vec4<T> operator/(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
vec4<T> rt(lhs);
|
||||
return rt /= rhs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Comparison operators
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
// equality
|
||||
friend bool operator==(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] == rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// inequality
|
||||
friend bool operator!=(const vec4<T> &lhs, const vec4<T> &rhs) {
|
||||
bool r = true;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r &= lhs._array[i] != rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// data intentionally left public to allow vec2.x
|
||||
union {
|
||||
struct {
|
||||
T x, y, z, w; // standard names for components
|
||||
};
|
||||
struct {
|
||||
T s, t, r, q; // standard names for components
|
||||
};
|
||||
T _array[4]; // array access
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic vector operations
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// compute the dot product of two vectors
|
||||
template <class T>
|
||||
inline typename T::value_type dot(const T &lhs, const T &rhs) {
|
||||
typename T::value_type r = 0;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
r += lhs._array[i] * rhs._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// return the length of the provided vector
|
||||
template <class T>
|
||||
inline typename T::value_type length(const T &vec) {
|
||||
typename T::value_type r = 0;
|
||||
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
r += vec._array[i] * vec._array[i];
|
||||
}
|
||||
|
||||
return typename T::value_type(sqrt(r));
|
||||
}
|
||||
|
||||
// return the squared norm
|
||||
template <class T>
|
||||
inline typename T::value_type square_norm(const T &vec) {
|
||||
typename T::value_type r = 0;
|
||||
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
r += vec._array[i] * vec._array[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// return the normalized version of the vector
|
||||
template <class T>
|
||||
inline T normalize(const T &vec) {
|
||||
typename T::value_type sum(0);
|
||||
T r;
|
||||
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
sum += vec._array[i] * vec._array[i];
|
||||
}
|
||||
|
||||
sum = typename T::value_type(sqrt(sum));
|
||||
|
||||
if (sum > 0)
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
r._array[i] = vec._array[i] / sum;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// In VC8 : min and max are already defined by a #define...
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
// componentwise min
|
||||
template <class T>
|
||||
inline T min(const T &lhs, const T &rhs) {
|
||||
T rt;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
rt._array[i] = std::min(lhs._array[i], rhs._array[i]);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
// componentwise max
|
||||
template <class T>
|
||||
inline T max(const T &lhs, const T &rhs) {
|
||||
T rt;
|
||||
|
||||
for (int i = 0; i < lhs.size(); i++) {
|
||||
rt._array[i] = std::max(lhs._array[i], rhs._array[i]);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
943
Samples/smokeParticles/particleDemo.cpp
Normal file
943
Samples/smokeParticles/particleDemo.cpp
Normal file
@@ -0,0 +1,943 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
CUDA particle system with volumetric shadows
|
||||
sgreen 11/2008
|
||||
|
||||
This sample demonstrates a technique for rendering realistic volumetric
|
||||
shadows through a cloud of particles. It uses CUDA for the simulation and
|
||||
depth sorting of the particles, and OpenGL for rendering.
|
||||
|
||||
See the accompanying documentation for more details on the algorithm.
|
||||
|
||||
This file handles OpenGL initialization and the user interface.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
#include <helper_gl.h>
|
||||
#if defined(__APPLE__) || defined(__MACOSX)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
#if defined(WIN32)
|
||||
#include <GL/wglew.h>
|
||||
#endif
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include <helper_cuda.h>
|
||||
|
||||
#include "ParticleSystem.h"
|
||||
#include "ParticleSystem.cuh"
|
||||
#include "SmokeRenderer.h"
|
||||
#include "paramgl.h"
|
||||
#include "GLSLProgram.h"
|
||||
#include "SmokeShaders.h"
|
||||
|
||||
uint numParticles = 1 << 16;
|
||||
|
||||
ParticleSystem *psystem = 0;
|
||||
SmokeRenderer *renderer = 0;
|
||||
GLSLProgram *floorProg = 0;
|
||||
|
||||
int winWidth = 1280, winHeight = 1024;
|
||||
int g_TotalErrors = 0;
|
||||
|
||||
// view params
|
||||
int ox, oy;
|
||||
int buttonState = 0;
|
||||
bool keyDown[256];
|
||||
|
||||
vec3f cameraPos(0, -1, -4);
|
||||
vec3f cameraRot(0, 0, 0);
|
||||
vec3f cameraPosLag(cameraPos);
|
||||
vec3f cameraRotLag(cameraRot);
|
||||
vec3f cursorPos(0, 1, 0);
|
||||
vec3f cursorPosLag(cursorPos);
|
||||
|
||||
vec3f lightPos(5.0, 5.0, -5.0);
|
||||
|
||||
const float inertia = 0.1f;
|
||||
const float translateSpeed = 0.002f;
|
||||
const float cursorSpeed = 0.01f;
|
||||
const float rotateSpeed = 0.2f;
|
||||
const float walkSpeed = 0.05f;
|
||||
|
||||
enum { M_VIEW = 0, M_MOVE_CURSOR, M_MOVE_LIGHT };
|
||||
int mode = 0;
|
||||
int displayMode = (int)SmokeRenderer::VOLUMETRIC;
|
||||
|
||||
// QA AutoTest
|
||||
bool g_bQAReadback = false;
|
||||
|
||||
// toggles
|
||||
bool displayEnabled = true;
|
||||
bool paused = false;
|
||||
bool displaySliders = false;
|
||||
bool wireframe = false;
|
||||
bool animateEmitter = true;
|
||||
bool emitterOn = true;
|
||||
bool sort = true;
|
||||
bool displayLightBuffer = false;
|
||||
bool drawVectors = false;
|
||||
bool doBlur = false;
|
||||
|
||||
float emitterVel = 0.0f;
|
||||
uint emitterRate = 1000;
|
||||
float emitterRadius = 0.25;
|
||||
float emitterSpread = 0.0;
|
||||
uint emitterIndex = 0;
|
||||
|
||||
// simulation parameters
|
||||
float timestep = 0.5f;
|
||||
float currentTime = 0.0f;
|
||||
float spriteSize = 0.05f;
|
||||
float alpha = 0.1f;
|
||||
float shadowAlpha = 0.02f;
|
||||
float particleLifetime = (float)numParticles / (float)emitterRate;
|
||||
vec3f lightColor(1.0f, 1.0f, 0.8f);
|
||||
vec3f colorAttenuation(0.5f, 0.75f, 1.0f);
|
||||
float blurRadius = 2.0f;
|
||||
|
||||
int numSlices = 64;
|
||||
int numDisplayedSlices = numSlices;
|
||||
|
||||
// fps
|
||||
static int fpsCount = 0;
|
||||
static int fpsLimit = 1;
|
||||
StopWatchInterface *timer = NULL;
|
||||
|
||||
float modelView[16];
|
||||
ParamListGL *params;
|
||||
|
||||
GLuint floorTex = 0;
|
||||
|
||||
// CheckRender object for verification
|
||||
#define MAX_EPSILON_ERROR 10.0f
|
||||
#define THRESHOLD 0.40f
|
||||
|
||||
// Define the files that are to be saved and the reference images for validation
|
||||
const char *sSDKsample = "CUDA Smoke Particles";
|
||||
|
||||
const char *sRefBin[] = {"ref_smokePart_pos.bin", "ref_smokePart_vel.bin",
|
||||
NULL};
|
||||
|
||||
void runEmitter();
|
||||
|
||||
// initialize particle system
|
||||
void initParticles(int numParticles, bool bUseVBO, bool bUseGL) {
|
||||
psystem = new ParticleSystem(numParticles, bUseVBO, bUseGL);
|
||||
psystem->reset(ParticleSystem::CONFIG_RANDOM);
|
||||
|
||||
if (bUseVBO) {
|
||||
renderer = new SmokeRenderer(numParticles);
|
||||
renderer->setLightTarget(vec3f(0.0, 1.0, 0.0));
|
||||
|
||||
sdkCreateTimer(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
if (psystem) {
|
||||
delete psystem;
|
||||
}
|
||||
|
||||
if (renderer) {
|
||||
delete renderer;
|
||||
}
|
||||
|
||||
if (floorProg) {
|
||||
delete floorProg;
|
||||
}
|
||||
|
||||
sdkDeleteTimer(&timer);
|
||||
|
||||
if (params) {
|
||||
delete params;
|
||||
}
|
||||
|
||||
if (floorTex) {
|
||||
glDeleteTextures(1, &floorTex);
|
||||
}
|
||||
}
|
||||
|
||||
void renderScene() {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// draw floor
|
||||
floorProg->enable();
|
||||
floorProg->bindTexture("tex", floorTex, GL_TEXTURE_2D, 0);
|
||||
floorProg->bindTexture("shadowTex", renderer->getShadowTexture(),
|
||||
GL_TEXTURE_2D, 1);
|
||||
floorProg->setUniformfv("lightPosEye", renderer->getLightPositionEyeSpace(),
|
||||
3);
|
||||
floorProg->setUniformfv("lightColor", lightColor, 3);
|
||||
|
||||
// set shadow matrix as texture matrix
|
||||
matrix4f shadowMatrix = renderer->getShadowMatrix();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf((GLfloat *)shadowMatrix.get_value());
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glNormal3f(0.0, 1.0, 0.0);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
float s = 20.f;
|
||||
float rep = 20.f;
|
||||
glTexCoord2f(0.f, 0.f);
|
||||
glVertex3f(-s, 0, -s);
|
||||
glTexCoord2f(rep, 0.f);
|
||||
glVertex3f(s, 0, -s);
|
||||
glTexCoord2f(rep, rep);
|
||||
glVertex3f(s, 0, s);
|
||||
glTexCoord2f(0.f, rep);
|
||||
glVertex3f(-s, 0, s);
|
||||
}
|
||||
glEnd();
|
||||
floorProg->disable();
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
|
||||
// draw light
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glTranslatef(lightPos.x, lightPos.y, lightPos.z);
|
||||
glColor3fv(&lightColor[0]);
|
||||
glutSolidSphere(0.1, 10, 5);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// main rendering loop
|
||||
void display() {
|
||||
sdkStartTimer(&timer);
|
||||
|
||||
// move camera
|
||||
if (cameraPos[1] > 0.0f) {
|
||||
cameraPos[1] = 0.0f;
|
||||
}
|
||||
|
||||
cameraPosLag += (cameraPos - cameraPosLag) * inertia;
|
||||
cameraRotLag += (cameraRot - cameraRotLag) * inertia;
|
||||
cursorPosLag += (cursorPos - cursorPosLag) * inertia;
|
||||
|
||||
// view transform
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glRotatef(cameraRotLag[0], 1.0, 0.0, 0.0);
|
||||
glRotatef(cameraRotLag[1], 0.0, 1.0, 0.0);
|
||||
glTranslatef(cameraPosLag[0], cameraPosLag[1], cameraPosLag[2]);
|
||||
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
|
||||
|
||||
// update the simulation
|
||||
if (!paused) {
|
||||
if (emitterOn) {
|
||||
runEmitter();
|
||||
}
|
||||
|
||||
SimParams &p = psystem->getParams();
|
||||
p.cursorPos = make_float3(cursorPosLag.x, cursorPosLag.y, cursorPosLag.z);
|
||||
|
||||
psystem->step(timestep);
|
||||
currentTime += timestep;
|
||||
}
|
||||
|
||||
renderer->calcVectors();
|
||||
vec3f sortVector = renderer->getSortVector();
|
||||
|
||||
psystem->setSortVector(make_float3(sortVector.x, sortVector.y, sortVector.z));
|
||||
psystem->setModelView(modelView);
|
||||
psystem->setSorting(sort);
|
||||
psystem->depthSort();
|
||||
|
||||
// render
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
renderScene();
|
||||
|
||||
// draw particles
|
||||
if (displayEnabled) {
|
||||
// render scene to offscreen buffers to get correct occlusion
|
||||
renderer->beginSceneRender(SmokeRenderer::LIGHT_BUFFER);
|
||||
renderScene();
|
||||
renderer->endSceneRender(SmokeRenderer::LIGHT_BUFFER);
|
||||
|
||||
renderer->beginSceneRender(SmokeRenderer::SCENE_BUFFER);
|
||||
renderScene();
|
||||
renderer->endSceneRender(SmokeRenderer::SCENE_BUFFER);
|
||||
|
||||
renderer->setPositionBuffer(psystem->getPosBuffer());
|
||||
renderer->setVelocityBuffer(psystem->getVelBuffer());
|
||||
renderer->setIndexBuffer(psystem->getSortedIndexBuffer());
|
||||
|
||||
renderer->setNumParticles(psystem->getNumParticles());
|
||||
renderer->setParticleRadius(spriteSize);
|
||||
renderer->setDisplayLightBuffer(displayLightBuffer);
|
||||
renderer->setAlpha(alpha);
|
||||
renderer->setShadowAlpha(shadowAlpha);
|
||||
renderer->setLightPosition(lightPos);
|
||||
renderer->setColorAttenuation(colorAttenuation);
|
||||
renderer->setLightColor(lightColor);
|
||||
renderer->setNumSlices(numSlices);
|
||||
renderer->setNumDisplayedSlices(numDisplayedSlices);
|
||||
renderer->setBlurRadius(blurRadius);
|
||||
|
||||
renderer->render();
|
||||
|
||||
if (drawVectors) {
|
||||
renderer->debugVectors();
|
||||
}
|
||||
}
|
||||
|
||||
// display sliders
|
||||
if (displaySliders) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); // invert color
|
||||
glEnable(GL_BLEND);
|
||||
params->Render(0, 0);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
glutSwapBuffers();
|
||||
glutReportErrors();
|
||||
sdkStopTimer(&timer);
|
||||
|
||||
fpsCount++;
|
||||
|
||||
// this displays the frame rate updated every second (independent of frame
|
||||
// rate)
|
||||
if (fpsCount >= fpsLimit) {
|
||||
char fps[256];
|
||||
float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
|
||||
sprintf(fps, "CUDA Smoke Particles (%d particles): %3.1f fps", numParticles,
|
||||
ifps);
|
||||
glutSetWindowTitle(fps);
|
||||
fpsCount = 0;
|
||||
fpsLimit = (ifps > 1.f) ? (int)ifps : 1;
|
||||
|
||||
if (paused) {
|
||||
fpsLimit = 0;
|
||||
}
|
||||
|
||||
sdkResetTimer(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
// GLUT callback functions
|
||||
void reshape(int w, int h) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(60.0, (float)w / (float)h, 0.01, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
renderer->setFOV(60.0);
|
||||
renderer->setWindowSize(w, h);
|
||||
}
|
||||
|
||||
void mouse(int button, int state, int x, int y) {
|
||||
int mods;
|
||||
|
||||
if (state == GLUT_DOWN) {
|
||||
buttonState |= 1 << button;
|
||||
} else if (state == GLUT_UP) {
|
||||
buttonState = 0;
|
||||
}
|
||||
|
||||
mods = glutGetModifiers();
|
||||
|
||||
if (mods & GLUT_ACTIVE_SHIFT) {
|
||||
buttonState = 2;
|
||||
} else if (mods & GLUT_ACTIVE_CTRL) {
|
||||
buttonState = 3;
|
||||
}
|
||||
|
||||
ox = x;
|
||||
oy = y;
|
||||
|
||||
if (displaySliders) {
|
||||
if (params->Mouse(x, y, button, state)) {
|
||||
glutPostRedisplay();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
// transform vector by matrix
|
||||
void xform(vec3f &v, vec3f &r, float *m) {
|
||||
r.x = v.x * m[0] + v.y * m[4] + v.z * m[8] + m[12];
|
||||
r.y = v.x * m[1] + v.y * m[5] + v.z * m[9] + m[13];
|
||||
r.z = v.x * m[2] + v.y * m[6] + v.z * m[10] + m[14];
|
||||
}
|
||||
|
||||
// transform vector by transpose of matrix (assuming orthonormal)
|
||||
void ixform(vec3f &v, vec3f &r, float *m) {
|
||||
r.x = v.x * m[0] + v.y * m[1] + v.z * m[2];
|
||||
r.y = v.x * m[4] + v.y * m[5] + v.z * m[6];
|
||||
r.z = v.x * m[8] + v.y * m[9] + v.z * m[10];
|
||||
}
|
||||
|
||||
void ixformPoint(vec3f &v, vec3f &r, float *m) {
|
||||
vec3f x;
|
||||
x.x = v.x - m[12];
|
||||
x.y = v.y - m[13];
|
||||
x.z = v.z - m[14];
|
||||
ixform(x, r, m);
|
||||
}
|
||||
|
||||
void motion(int x, int y) {
|
||||
float dx, dy;
|
||||
dx = (float)(x - ox);
|
||||
dy = (float)(y - oy);
|
||||
|
||||
if (displaySliders) {
|
||||
if (params->Motion(x, y)) {
|
||||
ox = x;
|
||||
oy = y;
|
||||
glutPostRedisplay();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case M_VIEW: {
|
||||
if (buttonState == 1) {
|
||||
// left = rotate
|
||||
cameraRot[0] += dy * rotateSpeed;
|
||||
cameraRot[1] += dx * rotateSpeed;
|
||||
}
|
||||
|
||||
if (buttonState == 2) {
|
||||
// middle = translate
|
||||
vec3f v = vec3f(dx * translateSpeed, -dy * translateSpeed, 0.0f);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
cameraPos += r;
|
||||
}
|
||||
|
||||
if (buttonState == 3) {
|
||||
// left+middle = zoom
|
||||
vec3f v = vec3f(0.0, 0.0, dy * translateSpeed);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
cameraPos += r;
|
||||
}
|
||||
} break;
|
||||
|
||||
case M_MOVE_CURSOR: {
|
||||
if (buttonState == 1) {
|
||||
vec3f v = vec3f(dx * cursorSpeed, -dy * cursorSpeed, 0.0f);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
cursorPos += r;
|
||||
} else if (buttonState == 2) {
|
||||
vec3f v = vec3f(0.0f, 0.0f, dy * cursorSpeed);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
cursorPos += r;
|
||||
}
|
||||
} break;
|
||||
|
||||
case M_MOVE_LIGHT:
|
||||
if (buttonState == 1) {
|
||||
vec3f v = vec3f(dx * cursorSpeed, -dy * cursorSpeed, 0.0f);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
lightPos += r;
|
||||
} else if (buttonState == 2) {
|
||||
vec3f v = vec3f(0.0f, 0.0f, dy * cursorSpeed);
|
||||
vec3f r;
|
||||
ixform(v, r, modelView);
|
||||
lightPos += r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ox = x;
|
||||
oy = y;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
// commented out to remove unused parameter warnings in Linux
|
||||
void key(unsigned char key, int /*x*/, int /*y*/) {
|
||||
switch (key) {
|
||||
case ' ':
|
||||
paused = !paused;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
psystem->step(timestep);
|
||||
renderer->setPositionBuffer(psystem->getPosBuffer());
|
||||
renderer->setVelocityBuffer(psystem->getVelBuffer());
|
||||
break;
|
||||
|
||||
case '\033':
|
||||
cleanup();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
mode = M_VIEW;
|
||||
animateEmitter = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
mode = M_MOVE_CURSOR;
|
||||
animateEmitter = false;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
mode = M_MOVE_LIGHT;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
displayEnabled = !displayEnabled;
|
||||
break;
|
||||
|
||||
case '1':
|
||||
psystem->reset(ParticleSystem::CONFIG_RANDOM);
|
||||
break;
|
||||
|
||||
case '2':
|
||||
emitterOn ^= 1;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
wireframe = !wireframe;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
displaySliders = !displaySliders;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
sort ^= 1;
|
||||
psystem->setSorting(sort);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
displayLightBuffer ^= 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
displayMode = (displayMode + 1) % SmokeRenderer::NUM_MODES;
|
||||
renderer->setDisplayMode((SmokeRenderer::DisplayMode)displayMode);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
displayMode--;
|
||||
|
||||
if (displayMode < 0) {
|
||||
displayMode = SmokeRenderer::NUM_MODES - 1;
|
||||
}
|
||||
|
||||
renderer->setDisplayMode((SmokeRenderer::DisplayMode)displayMode);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
drawVectors ^= 1;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
numSlices *= 2;
|
||||
|
||||
if (numSlices > 256) {
|
||||
numSlices = 256;
|
||||
}
|
||||
|
||||
numDisplayedSlices = numSlices;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (numSlices > 1) {
|
||||
numSlices /= 2;
|
||||
}
|
||||
|
||||
numDisplayedSlices = numSlices;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
doBlur ^= 1;
|
||||
renderer->setDoBlur(doBlur);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("numSlices = %d\n", numSlices);
|
||||
keyDown[key] = true;
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void keyUp(unsigned char key, int /*x*/, int /*y*/) { keyDown[key] = false; }
|
||||
|
||||
void runEmitter() {
|
||||
vec3f vel = vec3f(0, emitterVel, 0);
|
||||
vec3f vx(1, 0, 0);
|
||||
vec3f vy(0, 0, 1);
|
||||
vec3f spread(emitterSpread, 0.0f, emitterSpread);
|
||||
|
||||
psystem->sphereEmitter(emitterIndex, cursorPosLag, vel, spread, emitterRadius,
|
||||
ftoi(emitterRate * timestep), particleLifetime,
|
||||
particleLifetime * 0.1f);
|
||||
|
||||
if (emitterIndex > numParticles - 1) {
|
||||
emitterIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void special(int k, int x, int y) {
|
||||
if (displaySliders) {
|
||||
params->Special(k, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void idle(void) {
|
||||
// move camera in view direction
|
||||
/*
|
||||
0 4 8 12 x
|
||||
1 5 9 13 y
|
||||
2 6 10 14 z
|
||||
*/
|
||||
if (keyDown['w']) {
|
||||
cameraPos[0] += modelView[2] * walkSpeed;
|
||||
cameraPos[1] += modelView[6] * walkSpeed;
|
||||
cameraPos[2] += modelView[10] * walkSpeed;
|
||||
}
|
||||
|
||||
if (keyDown['s']) {
|
||||
cameraPos[0] -= modelView[2] * walkSpeed;
|
||||
cameraPos[1] -= modelView[6] * walkSpeed;
|
||||
cameraPos[2] -= modelView[10] * walkSpeed;
|
||||
}
|
||||
|
||||
if (keyDown['a']) {
|
||||
cameraPos[0] += modelView[0] * walkSpeed;
|
||||
cameraPos[1] += modelView[4] * walkSpeed;
|
||||
cameraPos[2] += modelView[8] * walkSpeed;
|
||||
}
|
||||
|
||||
if (keyDown['d']) {
|
||||
cameraPos[0] -= modelView[0] * walkSpeed;
|
||||
cameraPos[1] -= modelView[4] * walkSpeed;
|
||||
cameraPos[2] -= modelView[8] * walkSpeed;
|
||||
}
|
||||
|
||||
if (keyDown['e']) {
|
||||
cameraPos[0] += modelView[1] * walkSpeed;
|
||||
cameraPos[1] += modelView[5] * walkSpeed;
|
||||
cameraPos[2] += modelView[9] * walkSpeed;
|
||||
}
|
||||
|
||||
if (keyDown['q']) {
|
||||
cameraPos[0] -= modelView[1] * walkSpeed;
|
||||
cameraPos[1] -= modelView[5] * walkSpeed;
|
||||
cameraPos[2] -= modelView[9] * walkSpeed;
|
||||
}
|
||||
|
||||
if (animateEmitter) {
|
||||
const float speed = 0.02f;
|
||||
cursorPos.x = sin(currentTime * speed) * 1.5f;
|
||||
cursorPos.y = 1.5f + sin(currentTime * speed * 1.3f);
|
||||
cursorPos.z = cos(currentTime * speed) * 1.5f;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
// initialize sliders
|
||||
void initParams() {
|
||||
// create a new parameter list
|
||||
params = new ParamListGL("misc");
|
||||
|
||||
params->AddParam(new Param<int>("displayed slices", numDisplayedSlices, 0,
|
||||
256, 1, &numDisplayedSlices));
|
||||
|
||||
params->AddParam(
|
||||
new Param<float>("time step", timestep, 0.0f, 1.0f, 0.001f, ×tep));
|
||||
|
||||
SimParams &p = psystem->getParams();
|
||||
params->AddParam(
|
||||
new Param<float>("damping", 0.99f, 0.0f, 1.0f, 0.001f, &p.globalDamping));
|
||||
params->AddParam(
|
||||
new Param<float>("gravity", 0.0f, 0.01f, -0.01f, 0.0001f, &p.gravity.y));
|
||||
|
||||
params->AddParam(
|
||||
new Param<float>("noise freq", 0.1f, 0.0f, 1.0f, 0.001f, &p.noiseFreq));
|
||||
params->AddParam(new Param<float>("noise strength", 0.001f, 0.0f, 0.01f,
|
||||
0.001f, &p.noiseAmp));
|
||||
params->AddParam(new Param<float>("noise anim", 0.0f, -0.001f, 0.001f,
|
||||
0.0001f, &p.noiseSpeed.y));
|
||||
|
||||
params->AddParam(new Param<float>("sprite size", spriteSize, 0.0f, 0.1f,
|
||||
0.001f, &spriteSize));
|
||||
params->AddParam(
|
||||
new Param<float>("alpha", alpha, 0.0f, 1.0f, 0.001f, &alpha));
|
||||
|
||||
params->AddParam(new Param<float>("light color r", lightColor[0], 0.0f, 1.0f,
|
||||
0.01f, &lightColor[0]));
|
||||
params->AddParam(new Param<float>("light color g", lightColor[1], 0.0f, 1.0f,
|
||||
0.01f, &lightColor[1]));
|
||||
params->AddParam(new Param<float>("light color b", lightColor[2], 0.0f, 1.0f,
|
||||
0.01f, &lightColor[2]));
|
||||
|
||||
params->AddParam(new Param<float>("atten color r", colorAttenuation[0], 0.0f,
|
||||
1.0f, 0.01f, &colorAttenuation[0]));
|
||||
params->AddParam(new Param<float>("atten color g", colorAttenuation[1], 0.0f,
|
||||
1.0f, 0.01f, &colorAttenuation[1]));
|
||||
params->AddParam(new Param<float>("atten color b", colorAttenuation[2], 0.0f,
|
||||
1.0f, 0.01f, &colorAttenuation[2]));
|
||||
params->AddParam(new Param<float>("shadow alpha", shadowAlpha, 0.0f, 0.1f,
|
||||
0.001f, &shadowAlpha));
|
||||
|
||||
params->AddParam(new Param<float>("blur radius", blurRadius, 0.0f, 10.0f,
|
||||
0.1f, &blurRadius));
|
||||
|
||||
params->AddParam(new Param<float>("emitter radius", emitterRadius, 0.0f, 2.0f,
|
||||
0.01f, &emitterRadius));
|
||||
params->AddParam(
|
||||
new Param<uint>("emitter rate", emitterRate, 0, 10000, 1, &emitterRate));
|
||||
params->AddParam(new Param<float>("emitter velocity", emitterVel, 0.0f, 0.1f,
|
||||
0.001f, &emitterVel));
|
||||
params->AddParam(new Param<float>("emitter spread", emitterSpread, 0.0f, 0.1f,
|
||||
0.001f, &emitterSpread));
|
||||
|
||||
params->AddParam(new Param<float>("particle lifetime", particleLifetime, 0.0f,
|
||||
1000.0f, 1.0f, &particleLifetime));
|
||||
}
|
||||
|
||||
void mainMenu(int i) { key((unsigned char)i, 0, 0); }
|
||||
|
||||
void initMenus() {
|
||||
glutCreateMenu(mainMenu);
|
||||
glutAddMenuEntry("Reset block [1]", '1');
|
||||
glutAddMenuEntry("Toggle emitter [2]", '2');
|
||||
glutAddMenuEntry("Toggle animation [ ]", ' ');
|
||||
glutAddMenuEntry("Step animation [ret]", 13);
|
||||
glutAddMenuEntry("View mode [v]", 'v');
|
||||
glutAddMenuEntry("Move cursor mode [m]", 'm');
|
||||
glutAddMenuEntry("Move light mode [l]", 'l');
|
||||
glutAddMenuEntry("Toggle point rendering [p]", 'p');
|
||||
glutAddMenuEntry("Toggle sliders [h]", 'h');
|
||||
glutAddMenuEntry("Toggle sorting [o]", 'o');
|
||||
glutAddMenuEntry("Toggle vectors [V]", 'V');
|
||||
glutAddMenuEntry("Display light buffer [D]", 'D');
|
||||
glutAddMenuEntry("Toggle shadow blur [b]", 'b');
|
||||
glutAddMenuEntry("Increase no. slices [=]", '=');
|
||||
glutAddMenuEntry("Decrease no. slices [-]", '-');
|
||||
glutAddMenuEntry("Quit (esc)", '\033');
|
||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||
}
|
||||
|
||||
GLuint createTexture(GLenum target, GLint internalformat, GLenum format, int w,
|
||||
int h, void *data) {
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(target, 0, internalformat, w, h, 0, format, GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
return tex;
|
||||
}
|
||||
|
||||
GLuint loadTexture(char *filename) {
|
||||
unsigned char *data = 0;
|
||||
unsigned int width, height;
|
||||
sdkLoadPPM4ub(filename, &data, &width, &height);
|
||||
|
||||
if (!data) {
|
||||
printf("Error opening file '%s'\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Loaded '%s', %d x %d pixels\n", filename, width, height);
|
||||
|
||||
return createTexture(GL_TEXTURE_2D, GL_RGBA8, GL_RGBA, width, height, data);
|
||||
}
|
||||
|
||||
// initialize OpenGL
|
||||
void initGL(int *argc, char **argv) {
|
||||
glutInit(argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
||||
glutInitWindowSize(winWidth, winHeight);
|
||||
glutCreateWindow("CUDA Smoke Particles");
|
||||
|
||||
if (!isGLVersionSupported(2, 0)) {
|
||||
fprintf(stderr,
|
||||
"The following required OpenGL extensions "
|
||||
"missing:\n\tGL_VERSION_2_0\n\tGL_VERSION_1_5\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!areGLExtensionsSupported("GL_ARB_multitexture "
|
||||
"GL_ARB_vertex_buffer_object "
|
||||
"GL_EXT_geometry_shader4")) {
|
||||
fprintf(stderr,
|
||||
"The following required OpenGL extensions "
|
||||
"missing:\n\tGL_ARB_multitexture\n\tGL_ARB_vertex_buffer_"
|
||||
"object\n\tGL_EXT_geometry_shader4.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
if (wglewIsSupported("WGL_EXT_swap_control")) {
|
||||
// disable vertical sync
|
||||
wglSwapIntervalEXT(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// load floor texture
|
||||
char *imagePath = sdkFindFilePath("floortile.ppm", argv[0]);
|
||||
|
||||
if (imagePath == NULL) {
|
||||
fprintf(stderr, "Error finding floor image file\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
floorTex = loadTexture(imagePath);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
|
||||
|
||||
floorProg = new GLSLProgram(floorVS, floorPS);
|
||||
|
||||
glutReportErrors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program main
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv) {
|
||||
#if defined(__linux__)
|
||||
setenv("DISPLAY", ":0", 0);
|
||||
#endif
|
||||
|
||||
printf("%s Starting...\n\n", sSDKsample);
|
||||
|
||||
printf(
|
||||
"NOTE: The CUDA Samples are not meant for performance measurements. "
|
||||
"Results may vary when GPU Boost is enabled.\n\n");
|
||||
|
||||
if (argc > 1) {
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "n")) {
|
||||
numParticles = getCmdLineArgumentInt(argc, (const char **)argv, "n");
|
||||
}
|
||||
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "qatest")) {
|
||||
g_bQAReadback = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_bQAReadback) {
|
||||
// For Automated testing, we do not use OpenGL/CUDA interop
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
|
||||
// This code path is used for Automated Testing
|
||||
initParticles(numParticles, false, false);
|
||||
initParams();
|
||||
|
||||
if (emitterOn) {
|
||||
runEmitter();
|
||||
}
|
||||
|
||||
SimParams ¶ms = psystem->getParams();
|
||||
params.cursorPos =
|
||||
make_float3(cursorPosLag.x, cursorPosLag.y, cursorPosLag.z);
|
||||
|
||||
psystem->step(timestep);
|
||||
|
||||
float4 *pos = NULL, *vel = NULL;
|
||||
|
||||
psystem->dumpBin(&pos, &vel);
|
||||
|
||||
sdkDumpBin(pos, numParticles * sizeof(float4), "smokeParticles_pos.bin");
|
||||
sdkDumpBin(vel, numParticles * sizeof(float4), "smokeParticles_vel.bin");
|
||||
|
||||
if (!sdkCompareBin2BinFloat("smokeParticles_pos.bin", sRefBin[0],
|
||||
numParticles * sizeof(float4),
|
||||
MAX_EPSILON_ERROR, THRESHOLD, argv[0])) {
|
||||
g_TotalErrors++;
|
||||
}
|
||||
|
||||
if (!sdkCompareBin2BinFloat("smokeParticles_vel.bin", sRefBin[1],
|
||||
numParticles * sizeof(float4),
|
||||
MAX_EPSILON_ERROR, THRESHOLD, argv[0])) {
|
||||
g_TotalErrors++;
|
||||
}
|
||||
|
||||
delete psystem;
|
||||
} else {
|
||||
// Normal smokeParticles rendering path
|
||||
// 1st initialize OpenGL context, so we can properly set the GL for CUDA.
|
||||
// This is needed to achieve optimal performance with OpenGL/CUDA interop.
|
||||
initGL(&argc, argv);
|
||||
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
|
||||
// This is the normal code path for SmokeParticles
|
||||
initParticles(numParticles, true, true);
|
||||
initParams();
|
||||
initMenus();
|
||||
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutMouseFunc(mouse);
|
||||
glutMotionFunc(motion);
|
||||
glutKeyboardFunc(key);
|
||||
glutKeyboardUpFunc(keyUp);
|
||||
glutSpecialFunc(special);
|
||||
glutIdleFunc(idle);
|
||||
|
||||
glutMainLoop();
|
||||
}
|
||||
|
||||
exit(g_TotalErrors > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
49
Samples/smokeParticles/particles_kernel.cuh
Normal file
49
Samples/smokeParticles/particles_kernel.cuh
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
#ifndef PARTICLES_KERNEL_H
|
||||
#define PARTICLES_KERNEL_H
|
||||
|
||||
#include "vector_types.h"
|
||||
typedef unsigned int uint;
|
||||
|
||||
struct SimParams {
|
||||
float3 gravity;
|
||||
float globalDamping;
|
||||
float noiseFreq;
|
||||
float noiseAmp;
|
||||
float3 cursorPos;
|
||||
|
||||
float time;
|
||||
float3 noiseSpeed;
|
||||
};
|
||||
|
||||
struct float4x4 {
|
||||
float m[16];
|
||||
};
|
||||
|
||||
#endif
|
||||
110
Samples/smokeParticles/particles_kernel_device.cuh
Normal file
110
Samples/smokeParticles/particles_kernel_device.cuh
Normal file
@@ -0,0 +1,110 @@
|
||||
/* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CUDA Device code for particle simulation.
|
||||
*/
|
||||
|
||||
#ifndef _PARTICLES_KERNEL_H_
|
||||
#define _PARTICLES_KERNEL_H_
|
||||
|
||||
#include "helper_math.h"
|
||||
#include "math_constants.h"
|
||||
#include "particles_kernel.cuh"
|
||||
|
||||
cudaTextureObject_t noiseTex;
|
||||
// simulation parameters
|
||||
__constant__ SimParams params;
|
||||
|
||||
// look up in 3D noise texture
|
||||
__device__ float3 noise3D(float3 p, cudaTextureObject_t noiseTex) {
|
||||
float4 n = tex3D<float4>(noiseTex, p.x, p.y, p.z);
|
||||
return make_float3(n.x, n.y, n.z);
|
||||
}
|
||||
|
||||
// integrate particle attributes
|
||||
struct integrate_functor {
|
||||
float deltaTime;
|
||||
cudaTextureObject_t noiseTex;
|
||||
|
||||
__host__ __device__ integrate_functor(float delta_time,
|
||||
cudaTextureObject_t noise_Tex)
|
||||
: deltaTime(delta_time), noiseTex(noise_Tex) {}
|
||||
|
||||
template <typename Tuple>
|
||||
__device__ void operator()(Tuple t) {
|
||||
volatile float4 posData = thrust::get<2>(t);
|
||||
volatile float4 velData = thrust::get<3>(t);
|
||||
|
||||
float3 pos = make_float3(posData.x, posData.y, posData.z);
|
||||
float3 vel = make_float3(velData.x, velData.y, velData.z);
|
||||
|
||||
// update particle age
|
||||
float age = posData.w;
|
||||
float lifetime = velData.w;
|
||||
|
||||
if (age < lifetime) {
|
||||
age += deltaTime;
|
||||
} else {
|
||||
age = lifetime;
|
||||
}
|
||||
|
||||
// apply accelerations
|
||||
vel += params.gravity * deltaTime;
|
||||
|
||||
// apply procedural noise
|
||||
float3 noise = noise3D(
|
||||
pos * params.noiseFreq + params.time * params.noiseSpeed, noiseTex);
|
||||
vel += noise * params.noiseAmp;
|
||||
|
||||
// new position = old position + velocity * deltaTime
|
||||
pos += vel * deltaTime;
|
||||
|
||||
vel *= params.globalDamping;
|
||||
|
||||
// store new position and velocity
|
||||
thrust::get<0>(t) = make_float4(pos, age);
|
||||
thrust::get<1>(t) = make_float4(vel, velData.w);
|
||||
}
|
||||
};
|
||||
|
||||
struct calcDepth_functor {
|
||||
float3 sortVector;
|
||||
|
||||
__host__ __device__ calcDepth_functor(float3 sort_vector)
|
||||
: sortVector(sort_vector) {}
|
||||
|
||||
template <typename Tuple>
|
||||
__host__ __device__ void operator()(Tuple t) {
|
||||
volatile float4 p = thrust::get<0>(t);
|
||||
float key = -dot(make_float3(p.x, p.y, p.z),
|
||||
sortVector); // project onto sort vector
|
||||
thrust::get<1>(t) = key;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
131
Samples/smokeParticles/renderbuffer.cpp
Normal file
131
Samples/smokeParticles/renderbuffer.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2005,
|
||||
Aaron Lefohn (lefohn@cs.ucdavis.edu)
|
||||
Adam Moerschell (atmoerschell@ucdavis.edu)
|
||||
All rights reserved.
|
||||
|
||||
This software is licensed under the BSD open-source license. See
|
||||
http://www.opensource.org/licenses/bsd-license.php for more detail.
|
||||
|
||||
*************************************************************
|
||||
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 the University of California, Davis nor the names of
|
||||
the 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 AND CONTRIBUTORS
|
||||
"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.
|
||||
*/
|
||||
|
||||
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
||||
#include <helper_gl.h>
|
||||
#include "renderbuffer.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
Renderbuffer::Renderbuffer()
|
||||
: m_bufId(_CreateBufferId())
|
||||
{}
|
||||
|
||||
Renderbuffer::Renderbuffer(GLenum internalFormat, int width, int height)
|
||||
: m_bufId(_CreateBufferId())
|
||||
{
|
||||
Set(internalFormat, width, height);
|
||||
}
|
||||
|
||||
Renderbuffer::~Renderbuffer()
|
||||
{
|
||||
glDeleteRenderbuffersEXT(1, &m_bufId);
|
||||
}
|
||||
|
||||
void Renderbuffer::Bind()
|
||||
{
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId);
|
||||
}
|
||||
|
||||
void Renderbuffer::Unbind()
|
||||
{
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void Renderbuffer::Set(GLenum internalFormat, int width, int height)
|
||||
{
|
||||
int maxSize = Renderbuffer::GetMaxSize();
|
||||
|
||||
if (width > maxSize || height > maxSize)
|
||||
{
|
||||
cerr << "Renderbuffer::Renderbuffer() ERROR:\n\t"
|
||||
<< "Size too big (" << width << ", " << height << ")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Guarded bind
|
||||
GLint savedId = 0;
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &savedId);
|
||||
|
||||
if (savedId != (GLint)m_bufId)
|
||||
{
|
||||
Bind();
|
||||
}
|
||||
|
||||
// Allocate memory for renderBuffer
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height);
|
||||
|
||||
// Guarded unbind
|
||||
if (savedId != (GLint)m_bufId)
|
||||
{
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, savedId);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::GetId() const
|
||||
{
|
||||
return m_bufId;
|
||||
}
|
||||
|
||||
GLint Renderbuffer::GetMaxSize()
|
||||
{
|
||||
GLint maxAttach = 0;
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach);
|
||||
return maxAttach;
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::_CreateBufferId()
|
||||
{
|
||||
GLuint id = 0;
|
||||
glGenRenderbuffersEXT(1, &id);
|
||||
return id;
|
||||
}
|
||||
|
||||
107
Samples/smokeParticles/renderbuffer.h
Normal file
107
Samples/smokeParticles/renderbuffer.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||||
* with this source code for terms and conditions that govern your use of
|
||||
* this software. Any use, reproduction, disclosure, or distribution of
|
||||
* this software and related documentation outside the terms of the EULA
|
||||
* is strictly prohibited.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2005,
|
||||
Aaron Lefohn (lefohn@cs.ucdavis.edu)
|
||||
Adam Moerschell (atmoerschell@ucdavis.edu)
|
||||
All rights reserved.
|
||||
|
||||
This software is licensed under the BSD open-source license. See
|
||||
http://www.opensource.org/licenses/bsd-license.php for more detail.
|
||||
|
||||
*************************************************************
|
||||
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 the University of California, Davis nor the names of
|
||||
the 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 AND CONTRIBUTORS
|
||||
"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.
|
||||
*/
|
||||
|
||||
#ifndef UCDAVIS_RENDER_BUFFER_H
|
||||
#define UCDAVIS_RENDER_BUFFER_H
|
||||
|
||||
#include "framebufferObject.h"
|
||||
|
||||
/*!
|
||||
Renderbuffer Class. This class encapsulates the Renderbuffer OpenGL
|
||||
object described in the FramebufferObject (FBO) OpenGL spec.
|
||||
See the official spec at:
|
||||
http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
|
||||
for complete details.
|
||||
|
||||
A "Renderbuffer" is a chunk of GPU memory used by FramebufferObjects to
|
||||
represent "traditional" framebuffer memory (depth, stencil, and color buffers).
|
||||
By "traditional," we mean that the memory cannot be bound as a texture.
|
||||
With respect to GPU shaders, Renderbuffer memory is "write-only." Framebuffer
|
||||
operations such as alpha blending, depth test, alpha test, stencil test, etc.
|
||||
read from this memory in post-fragment-shader (ROP) operations.
|
||||
|
||||
The most common use of Renderbuffers is to create depth and stencil buffers.
|
||||
Note that as of 7/1/05, NVIDIA drivers to do not support stencil Renderbuffers.
|
||||
|
||||
Usage Notes:
|
||||
1) "internalFormat" can be any of the following:
|
||||
Valid OpenGL internal formats beginning with:
|
||||
RGB, RGBA, DEPTH_COMPONENT
|
||||
|
||||
or a stencil buffer format (not currently supported
|
||||
in NVIDIA drivers as of 7/1/05).
|
||||
STENCIL_INDEX1_EXT
|
||||
STENCIL_INDEX4_EXT
|
||||
STENCIL_INDEX8_EXT
|
||||
STENCIL_INDEX16_EXT
|
||||
*/
|
||||
class Renderbuffer
|
||||
{
|
||||
public:
|
||||
/// Ctors/Dtors
|
||||
Renderbuffer();
|
||||
Renderbuffer(GLenum internalFormat, int width, int height);
|
||||
~Renderbuffer();
|
||||
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void Set(GLenum internalFormat, int width, int height);
|
||||
GLuint GetId() const;
|
||||
|
||||
static GLint GetMaxSize();
|
||||
|
||||
private:
|
||||
GLuint m_bufId;
|
||||
static GLuint _CreateBufferId();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
20
Samples/smokeParticles/smokeParticles_vs2017.sln
Normal file
20
Samples/smokeParticles/smokeParticles_vs2017.sln
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2017
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smokeParticles", "smokeParticles_vs2017.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
143
Samples/smokeParticles/smokeParticles_vs2017.vcxproj
Normal file
143
Samples/smokeParticles/smokeParticles_vs2017.vcxproj
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
|
||||
<RootNamespace>smokeParticles_vs2017</RootNamespace>
|
||||
<ProjectName>smokeParticles</ProjectName>
|
||||
<CudaToolkitCustomDir />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'==''">
|
||||
<LatestTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</LatestTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
<TargetPlatformVersion>$(WindowsTargetPlatformVersion)</TargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(CUDAPropsPath)\CUDA 11.5.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IntDir>$(Platform)/$(Configuration)/</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules />
|
||||
<CodeAnalysisRuleAssemblies />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<OutDir>../../bin/win64/$(Configuration)/</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../Common;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalDependencies>cudart_static.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);../../Common/lib/$(PlatformName);</AdditionalLibraryDirectories>
|
||||
<OutputFile>$(OutDir)/smokeParticles.exe</OutputFile>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
|
||||
<AdditionalOptions>-Xcompiler "/wd 4819" %(AdditionalOptions)</AdditionalOptions>
|
||||
<Include>./;../../Common</Include>
|
||||
<Defines>WIN32</Defines>
|
||||
<AdditionalOptions>--threads 0</AdditionalOptions>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<Runtime>MTd</Runtime>
|
||||
<TargetMachinePlatform>64</TargetMachinePlatform>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<Runtime>MT</Runtime>
|
||||
<TargetMachinePlatform>64</TargetMachinePlatform>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
|
||||
<Link>
|
||||
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>glew64.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GLSLProgram.cpp" />
|
||||
<ClCompile Include="ParticleSystem.cpp" />
|
||||
<CudaCompile Include="ParticleSystem_cuda.cu" />
|
||||
<ClCompile Include="SmokeRenderer.cpp" />
|
||||
<ClCompile Include="SmokeShaders.cpp" />
|
||||
<ClCompile Include="framebufferObject.cpp" />
|
||||
<ClCompile Include="particleDemo.cpp" />
|
||||
<ClCompile Include="renderbuffer.cpp" />
|
||||
<ClInclude Include="GLSLProgram.h" />
|
||||
<ClInclude Include="GpuArray.h" />
|
||||
<ClInclude Include="ParticleSystem.h" />
|
||||
<ClInclude Include="SmokeRenderer.h" />
|
||||
<ClInclude Include="SmokeShaders.h" />
|
||||
<ClInclude Include="framebufferObject.h" />
|
||||
<ClInclude Include="nvMath.h" />
|
||||
<ClInclude Include="nvMatrix.h" />
|
||||
<ClInclude Include="nvQuaternion.h" />
|
||||
<ClInclude Include="nvVector.h" />
|
||||
<ClInclude Include="renderbuffer.h" />
|
||||
<None Include="ParticleSystem.cuh" />
|
||||
<None Include="particles_kernel.cuh" />
|
||||
<None Include="particles_kernel_device.cuh" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(CUDAPropsPath)\CUDA 11.5.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
20
Samples/smokeParticles/smokeParticles_vs2019.sln
Normal file
20
Samples/smokeParticles/smokeParticles_vs2019.sln
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2019
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smokeParticles", "smokeParticles_vs2019.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
|
||||
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
139
Samples/smokeParticles/smokeParticles_vs2019.vcxproj
Normal file
139
Samples/smokeParticles/smokeParticles_vs2019.vcxproj
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
|
||||
<RootNamespace>smokeParticles_vs2019</RootNamespace>
|
||||
<ProjectName>smokeParticles</ProjectName>
|
||||
<CudaToolkitCustomDir />
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(CUDAPropsPath)\CUDA 11.5.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IntDir>$(Platform)/$(Configuration)/</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules />
|
||||
<CodeAnalysisRuleAssemblies />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<OutDir>../../bin/win64/$(Configuration)/</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../Common;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalDependencies>cudart_static.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);../../Common/lib/$(PlatformName);</AdditionalLibraryDirectories>
|
||||
<OutputFile>$(OutDir)/smokeParticles.exe</OutputFile>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
|
||||
<AdditionalOptions>-Xcompiler "/wd 4819" %(AdditionalOptions)</AdditionalOptions>
|
||||
<Include>./;../../Common</Include>
|
||||
<Defines>WIN32</Defines>
|
||||
<AdditionalOptions>--threads 0</AdditionalOptions>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<Runtime>MTd</Runtime>
|
||||
<TargetMachinePlatform>64</TargetMachinePlatform>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<Runtime>MT</Runtime>
|
||||
<TargetMachinePlatform>64</TargetMachinePlatform>
|
||||
</CudaCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
|
||||
<Link>
|
||||
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>glew64.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GLSLProgram.cpp" />
|
||||
<ClCompile Include="ParticleSystem.cpp" />
|
||||
<CudaCompile Include="ParticleSystem_cuda.cu" />
|
||||
<ClCompile Include="SmokeRenderer.cpp" />
|
||||
<ClCompile Include="SmokeShaders.cpp" />
|
||||
<ClCompile Include="framebufferObject.cpp" />
|
||||
<ClCompile Include="particleDemo.cpp" />
|
||||
<ClCompile Include="renderbuffer.cpp" />
|
||||
<ClInclude Include="GLSLProgram.h" />
|
||||
<ClInclude Include="GpuArray.h" />
|
||||
<ClInclude Include="ParticleSystem.h" />
|
||||
<ClInclude Include="SmokeRenderer.h" />
|
||||
<ClInclude Include="SmokeShaders.h" />
|
||||
<ClInclude Include="framebufferObject.h" />
|
||||
<ClInclude Include="nvMath.h" />
|
||||
<ClInclude Include="nvMatrix.h" />
|
||||
<ClInclude Include="nvQuaternion.h" />
|
||||
<ClInclude Include="nvVector.h" />
|
||||
<ClInclude Include="renderbuffer.h" />
|
||||
<None Include="ParticleSystem.cuh" />
|
||||
<None Include="particles_kernel.cuh" />
|
||||
<None Include="particles_kernel_device.cuh" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(CUDAPropsPath)\CUDA 11.5.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user