mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
165 lines
3.8 KiB
C++
165 lines
3.8 KiB
C++
#include "GLDraw.h"
|
|
|
|
#ifdef GL_USE_SHADERS
|
|
|
|
namespace Upp {
|
|
|
|
static GLuint LoadShader(const char *src, GLenum type) {
|
|
GLuint shader;
|
|
GLint compiled;
|
|
|
|
shader = glCreateShader(type);
|
|
if(!shader)
|
|
return 0;
|
|
|
|
glShaderSource(shader, 1, &src, NULL);
|
|
glCompileShader(shader);
|
|
|
|
// Check the compile status
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
|
if(!compiled) {
|
|
String error = type == GL_VERTEX_SHADER ? "Vertex" : "Fragment";
|
|
error << " shader failed to compile ";
|
|
GLint infoLen = 0;
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
|
|
if(infoLen > 1) {
|
|
Buffer<char> infoLog(infoLen);
|
|
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
|
|
error << ~infoLog;
|
|
}
|
|
Panic(error);
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
GLint infoLen = 0;
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
|
|
if(infoLen > 1) {
|
|
Buffer<char> infoLog(infoLen);
|
|
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
|
|
}
|
|
#endif
|
|
|
|
return shader;
|
|
}
|
|
|
|
void GLProgram::Compile(const char *vertex_shader_, const char *fragment_shader_)
|
|
{
|
|
Clear();
|
|
|
|
program = glCreateProgram();
|
|
|
|
vertex_shader = LoadShader(vertex_shader_, GL_VERTEX_SHADER);
|
|
fragment_shader = LoadShader(fragment_shader_, GL_FRAGMENT_SHADER);
|
|
|
|
glAttachShader(program, vertex_shader);
|
|
glAttachShader(program, fragment_shader);
|
|
}
|
|
|
|
void GLProgram::Link()
|
|
{
|
|
glLinkProgram(program);
|
|
|
|
GLint linked;
|
|
|
|
glGetProgramiv(program, GL_LINK_STATUS, &linked);
|
|
if(!linked){
|
|
GLint infoLen = 0;
|
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
|
|
if(infoLen > 1) {
|
|
Buffer<char> infoLog(infoLen);
|
|
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
|
|
Panic(infoLog);
|
|
}
|
|
Panic("Failed to link");
|
|
Clear();
|
|
}
|
|
}
|
|
|
|
void GLProgram::Create(const char *vertex_shader_, const char *fragment_shader_,
|
|
Tuple2<int, const char *> *bind_attr, int bind_count)
|
|
{
|
|
Compile(vertex_shader_, fragment_shader_);
|
|
|
|
for(int i = 0; i < bind_count; i++)
|
|
glBindAttribLocation(program, bind_attr[i].a, bind_attr[i].b);
|
|
|
|
Link();
|
|
|
|
Use();
|
|
}
|
|
|
|
void GLProgram::Create(const char *vertex_shader, const char *fragment_shader,
|
|
int attr1, const char *attr1name)
|
|
{
|
|
Tuple2<int, const char *> bind[] = {
|
|
{ attr1, attr1name },
|
|
};
|
|
Create(vertex_shader, fragment_shader, bind, __countof(bind));
|
|
}
|
|
|
|
void GLProgram::Create(const char *vertex_shader, const char *fragment_shader,
|
|
int attr1, const char *attr1name,
|
|
int attr2, const char *attr2name)
|
|
{
|
|
Tuple2<int, const char *> bind[] = {
|
|
{ attr1, attr1name },
|
|
{ attr2, attr2name },
|
|
};
|
|
Create(vertex_shader, fragment_shader, bind, __countof(bind));
|
|
}
|
|
|
|
void GLProgram::Create(const char *vertex_shader, const char *fragment_shader,
|
|
int attr1, const char *attr1name,
|
|
int attr2, const char *attr2name,
|
|
int attr3, const char *attr3name)
|
|
{
|
|
Tuple2<int, const char *> bind[] = {
|
|
{ attr1, attr1name },
|
|
{ attr2, attr2name },
|
|
{ attr3, attr3name },
|
|
};
|
|
Create(vertex_shader, fragment_shader, bind, __countof(bind));
|
|
}
|
|
|
|
void GLProgram::Clear()
|
|
{
|
|
if(program)
|
|
glDeleteProgram(program);
|
|
if(vertex_shader)
|
|
glDeleteShader(vertex_shader);
|
|
if(fragment_shader)
|
|
glDeleteShader(fragment_shader);
|
|
}
|
|
|
|
extern int sProgramCounter;
|
|
|
|
void GLProgram::Use()
|
|
{
|
|
static int64 currentid;
|
|
if(currentid != serialid) {
|
|
currentid = serialid;
|
|
glUseProgram(program);
|
|
sProgramCounter++;
|
|
}
|
|
}
|
|
|
|
GLProgram::GLProgram()
|
|
{
|
|
static int64 h;
|
|
serialid = ++h;
|
|
vertex_shader = fragment_shader = program = 0;
|
|
}
|
|
|
|
GLProgram::~GLProgram()
|
|
{
|
|
if(program)
|
|
glDeleteProgram(program);
|
|
if(vertex_shader)
|
|
glDeleteShader(vertex_shader);
|
|
if(fragment_shader)
|
|
glDeleteShader(fragment_shader);
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|