205 lines
5.5 KiB
C++
205 lines
5.5 KiB
C++
|
#include "ogl.h"
|
||
|
|
||
|
#include <Kore/Graphics3/Graphics.h>
|
||
|
#include <Kore/Graphics4/Shader.h>
|
||
|
#include <Kore/Log.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <string>
|
||
|
|
||
|
using namespace Kore;
|
||
|
|
||
|
namespace Kore {
|
||
|
#ifndef OPENGLES
|
||
|
bool programUsesTessellation = false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
ProgramImpl::ProgramImpl()
|
||
|
: textureCount(0), vertexShader(nullptr), fragmentShader(nullptr), geometryShader(nullptr), tessellationEvaluationShader(nullptr),
|
||
|
tessellationControlShader(nullptr) {
|
||
|
textures = new const char *[16];
|
||
|
textureValues = new int[16];
|
||
|
}
|
||
|
|
||
|
Graphics4::Program::Program() {
|
||
|
programId = glCreateProgram();
|
||
|
glCheckErrors();
|
||
|
}
|
||
|
|
||
|
ProgramImpl::~ProgramImpl() {
|
||
|
glDeleteProgram(programId);
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::setVertexShader(Shader *shader) {
|
||
|
vertexShader = shader;
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::setFragmentShader(Shader *shader) {
|
||
|
fragmentShader = shader;
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::setGeometryShader(Shader *shader) {
|
||
|
#ifndef OPENGLES
|
||
|
geometryShader = shader;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::setTessellationControlShader(Shader *shader) {
|
||
|
#ifndef OPENGLES
|
||
|
tessellationControlShader = shader;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::setTessellationEvaluationShader(Shader *shader) {
|
||
|
#ifndef OPENGLES
|
||
|
tessellationEvaluationShader = shader;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
namespace {
|
||
|
int toGlShader(Graphics4::ShaderType type) {
|
||
|
switch (type) {
|
||
|
case Graphics4::VertexShader:
|
||
|
default:
|
||
|
return GL_VERTEX_SHADER;
|
||
|
case Graphics4::FragmentShader:
|
||
|
return GL_FRAGMENT_SHADER;
|
||
|
/*#ifndef OPENGLES
|
||
|
case GeometryShader:
|
||
|
return GL_GEOMETRY_SHADER;
|
||
|
case TessellationControlShader:
|
||
|
return GL_TESS_CONTROL_SHADER;
|
||
|
case TessellationEvaluationShader:
|
||
|
return GL_TESS_EVALUATION_SHADER;
|
||
|
#endif*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void compileShader(uint &id, char *source, int length, Graphics4::ShaderType type) {
|
||
|
id = glCreateShader(toGlShader(type));
|
||
|
glCheckErrors();
|
||
|
glShaderSource(id, 1, (const GLchar **)&source, 0);
|
||
|
glCompileShader(id);
|
||
|
|
||
|
int result;
|
||
|
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||
|
if (result != GL_TRUE) {
|
||
|
int length;
|
||
|
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
|
||
|
char *errormessage = new char[length];
|
||
|
glGetShaderInfoLog(id, length, nullptr, errormessage);
|
||
|
printf("GLSL compiler error: %s\n", errormessage);
|
||
|
delete[] errormessage;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::link(VertexStructure **structures, int count) {
|
||
|
compileShader(vertexShader->id, vertexShader->source, vertexShader->length, VertexShader);
|
||
|
compileShader(fragmentShader->id, fragmentShader->source, fragmentShader->length, FragmentShader);
|
||
|
#ifndef OPENGLES
|
||
|
if (geometryShader != nullptr)
|
||
|
compileShader(geometryShader->id, geometryShader->source, geometryShader->length, GeometryShader);
|
||
|
if (tessellationControlShader != nullptr)
|
||
|
compileShader(tessellationControlShader->id, tessellationControlShader->source, tessellationControlShader->length, TessellationControlShader);
|
||
|
if (tessellationEvaluationShader != nullptr)
|
||
|
compileShader(tessellationEvaluationShader->id, tessellationEvaluationShader->source, tessellationEvaluationShader->length,
|
||
|
TessellationEvaluationShader);
|
||
|
#endif
|
||
|
glAttachShader(programId, vertexShader->id);
|
||
|
glAttachShader(programId, fragmentShader->id);
|
||
|
#ifndef OPENGLES
|
||
|
if (geometryShader != nullptr)
|
||
|
glAttachShader(programId, geometryShader->id);
|
||
|
if (tessellationControlShader != nullptr)
|
||
|
glAttachShader(programId, tessellationControlShader->id);
|
||
|
if (tessellationEvaluationShader != nullptr)
|
||
|
glAttachShader(programId, tessellationEvaluationShader->id);
|
||
|
#endif
|
||
|
glCheckErrors();
|
||
|
|
||
|
int index = 0;
|
||
|
for (int i1 = 0; i1 < count; ++i1) {
|
||
|
for (int i2 = 0; i2 < structures[i1]->size; ++i2) {
|
||
|
VertexElement element = structures[i1]->elements[i2];
|
||
|
glBindAttribLocation(programId, index, element.name);
|
||
|
glCheckErrors();
|
||
|
if (element.data == Float4x4VertexData) {
|
||
|
index += 4;
|
||
|
}
|
||
|
else {
|
||
|
++index;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
glLinkProgram(programId);
|
||
|
|
||
|
int result;
|
||
|
glGetProgramiv(programId, GL_LINK_STATUS, &result);
|
||
|
if (result != GL_TRUE) {
|
||
|
int length;
|
||
|
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &length);
|
||
|
char *errormessage = new char[length];
|
||
|
glGetProgramInfoLog(programId, length, nullptr, errormessage);
|
||
|
printf("GLSL linker error: %s\n", errormessage);
|
||
|
delete[] errormessage;
|
||
|
}
|
||
|
|
||
|
#ifndef KINC_OPENGL_ES
|
||
|
#ifndef KINC_LINUX
|
||
|
/* if (tessellationControlShader != nullptr) {
|
||
|
glPatchParameteri(GL_PATCH_VERTICES, 3);
|
||
|
glCheckErrors();
|
||
|
}*/
|
||
|
#endif
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void Graphics4::Program::set() {
|
||
|
#ifndef KINC_OPENGL_ES
|
||
|
programUsesTessellation = tessellationControlShader != nullptr;
|
||
|
#endif
|
||
|
glUseProgram(programId);
|
||
|
glCheckErrors();
|
||
|
for (int index = 0; index < textureCount; ++index) {
|
||
|
glUniform1i(textureValues[index], index);
|
||
|
glCheckErrors();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Graphics4::ConstantLocation Graphics4::Program::getConstantLocation(const char *name) {
|
||
|
ConstantLocation location;
|
||
|
location.location = glGetUniformLocation(programId, name);
|
||
|
glCheckErrors();
|
||
|
if (location.location < 0) {
|
||
|
log(Warning, "Uniform %s not found.", name);
|
||
|
}
|
||
|
return location;
|
||
|
}
|
||
|
|
||
|
int ProgramImpl::findTexture(const char *name) {
|
||
|
for (int index = 0; index < textureCount; ++index) {
|
||
|
if (strcmp(textures[index], name) == 0)
|
||
|
return index;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
Graphics4::TextureUnit Graphics4::Program::getTextureUnit(const char *name) {
|
||
|
int index = findTexture(name);
|
||
|
if (index < 0) {
|
||
|
int location = glGetUniformLocation(programId, name);
|
||
|
glCheckErrors();
|
||
|
index = textureCount;
|
||
|
textureValues[index] = location;
|
||
|
textures[index] = name;
|
||
|
++textureCount;
|
||
|
}
|
||
|
TextureUnit unit;
|
||
|
unit.unit = index;
|
||
|
return unit;
|
||
|
}
|