Files
glest-source/source/shared_lib/sources/graphics/gl/shader_gl.cpp
2018-05-06 00:01:36 +02:00

255 lines
6.3 KiB
C++

// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "shader_gl.h"
#include <fstream>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared {
namespace Graphics {
namespace Gl {
// =====================================================
// class ShaderProgramGl
// =====================================================
ShaderProgramGl::ShaderProgramGl() {
inited = false;
vertexShader = 0;
fragmentShader = 0;
handle = 0;
}
void ShaderProgramGl::init() {
if (!inited) {
assertGl();
handle = glCreateProgramObjectARB();
assertGl();
inited = true;
}
}
void ShaderProgramGl::end() {
if (inited) {
assertGl();
glDeleteObjectARB(handle);
assertGl();
inited = false;
}
}
void ShaderProgramGl::attach(VertexShader *vertexShader, FragmentShader *fragmentShader) {
this->vertexShader = vertexShader;
this->fragmentShader = fragmentShader;
}
bool ShaderProgramGl::link(string &messages) {
assertGl();
VertexShaderGl *vertexShaderGl = static_cast<VertexShaderGl*>(vertexShader);
FragmentShaderGl *fragmentShaderGl = static_cast<FragmentShaderGl*>(fragmentShader);
const ShaderSource *vss = vertexShaderGl->getSource();
const ShaderSource *fss = fragmentShaderGl->getSource();
messages = "Linking program: " + vss->getPathInfo() + ", " + fss->getPathInfo() + "\n";
//attach
glAttachObjectARB(handle, vertexShaderGl->getHandle());
glAttachObjectARB(handle, fragmentShaderGl->getHandle());
assertGl();
//bind attributes
for (unsigned int i = 0; i < attributes.size(); ++i) {
//int a= attributes[i].second;
//string s= attributes[i].first;
glBindAttribLocationARB(handle, attributes[i].second, attributes[i].first.c_str());
}
assertGl();
//link
glLinkProgramARB(handle);
glValidateProgramARB(handle);
assertGl();
//log
GLint logLength = 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer = new char[logLength + 1];
glGetInfoLogARB(handle, logLength + 1, NULL, buffer);
messages += buffer;
delete[] buffer;
assertGl();
//status
GLint status = false;
glGetObjectParameterivARB(handle, GL_OBJECT_LINK_STATUS_ARB, &status);
assertGl();
return status != 0;
}
void ShaderProgramGl::activate() {
assertGl();
glUseProgramObjectARB(handle);
assertGl();
}
void ShaderProgramGl::deactivate() {
assertGl();
glUseProgramObjectARB(0);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, int value) {
assertGl();
glUniform1iARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, float value) {
assertGl();
glUniform1fARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec2f &value) {
assertGl();
glUniform2fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec3f &value) {
assertGl();
glUniform3fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec4f &value) {
assertGl();
glUniform4fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix3f &value) {
assertGl();
glUniformMatrix3fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix4f &value) {
assertGl();
glUniformMatrix4fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::bindAttribute(const string &name, int index) {
attributes.push_back(AttributePair(name, index));
}
GLint ShaderProgramGl::getLocation(const string &name) {
GLint location = glGetUniformLocationARB(handle, name.c_str());
if (location == -1) {
throw megaglest_runtime_error("Can't locate uniform: " + name);
}
return location;
}
// ===============================================
// class ShaderGl
// ===============================================
ShaderGl::ShaderGl() {
inited = false;
handle = 0;
}
void ShaderGl::load(const string &path) {
source.load(path);
}
bool ShaderGl::compile(string &messages) {
assertGl();
messages = "Compiling shader: " + source.getPathInfo() + "\n";
//load source
GLint length = (GLint) source.getCode().size();
const GLcharARB *csource = source.getCode().c_str();
glShaderSourceARB(handle, 1, &csource, &length);
//compile
glCompileShaderARB(handle);
//log
GLint logLength = 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer = new char[logLength + 1];
glGetInfoLogARB(handle, logLength + 1, NULL, buffer);
messages += buffer;
delete[] buffer;
//status
GLint status = false;
glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
assertGl();
return status != 0;
}
void ShaderGl::end() {
if (inited) {
assertGl();
glDeleteObjectARB(handle);
assertGl();
}
}
// ===============================================
// class VertexShaderGl
// ===============================================
void VertexShaderGl::init() {
if (!inited) {
assertGl();
handle = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
assertGl();
inited = true;
}
}
// ===============================================
// class FragmentShaderGl
// ===============================================
void FragmentShaderGl::init() {
if (!inited) {
assertGl();
handle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
assertGl();
inited = true;
}
}
}
}
}//end namespace