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

244 lines
6.9 KiB
C++

/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NVIDIA CORPORATION nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#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;
}