You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
7.2 KiB
256 lines
7.2 KiB
/* 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; |
|
}
|
|
|