Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/shader_data.cc @ 10555

Last change on this file since 10555 was 10143, checked in by bensch, 18 years ago

Shader fixing

File size: 7.3 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "shader_data.h"
19
20#include "stdlibincl.h"
21#include "compiler.h"
22//#include <stdio.h>
23#include <fstream>
24
25#include "debug.h"
26
27
28#ifndef PARSELINELENGTH
29#define PARSELINELENGTH     512       //!< how many chars to read at once
30#endif
31
32
33ObjectListDefinition(ShaderData);
34
35/**
36 * standard constructor
37*/
38ShaderData::ShaderData ()
39{
40  this->registerObject(this, ShaderData::_objectList);
41  this->shaderProgram = 0;
42  this->vertexShader = 0;
43  this->fragmentShader = 0;
44}
45
46
47/// TODO fix that shaders are unloaded first. then loaded
48bool ShaderData::load(const std::string& vertexShaderFile, const std::string& fragmentShaderFile)
49{
50  if (GLEW_ARB_shader_objects && GLEW_ARB_shading_language_100)
51  {
52    this->shaderProgram = glCreateProgramObjectARB();
53
54    if (!vertexShaderFile.empty())
55      this->loadShaderProgramm(ShaderData::Vertex, vertexShaderFile);
56    if (!fragmentShaderFile.empty())
57      this->loadShaderProgramm(ShaderData::Fragment, fragmentShaderFile);
58
59    this->linkShaderProgram();
60
61  }
62  else
63  {
64    PRINTF(2)("Shaders are not supported on your hardware\n");
65    return true;
66  }
67
68  return true;
69}
70
71/**
72 * standard deconstructor
73 */
74ShaderData::~ShaderData ()
75{
76  if (shaderProgram == 0)
77    return;
78
79
80  if (this->shaderProgram == glGetHandleARB(GL_PROGRAM_OBJECT_ARB))
81    glUseProgramObjectARB(0);
82
83  // delete what has to be deleted here
84  this->deleteProgram(ShaderData::Vertex);
85  this->deleteProgram(ShaderData::Fragment);
86
87  if (this->fragmentShader != 0)
88  {
89    glDetachObjectARB(this->shaderProgram, this->fragmentShader);
90    glDeleteObjectARB(this->fragmentShader);
91  }
92  if (this->vertexShader != 0)
93  {
94    glDetachObjectARB(this->shaderProgram, this->vertexShader);
95    glDeleteObjectARB(this->vertexShader);
96  }
97  if (this->shaderProgram != 0)
98  {
99    GLint status = 0;
100    //glLinkProgramARB(this->shaderProgram);
101    glDeleteObjectARB(this->shaderProgram);
102    // link error checking
103    glGetObjectParameterivARB(this->shaderProgram, GL_OBJECT_DELETE_STATUS_ARB, &status);
104    if (status == GL_INVALID_VALUE || status == GL_INVALID_OPERATION)
105      this->printError(this->shaderProgram);
106  }
107}
108
109bool ShaderData::loadShaderProgramm(ShaderData::Type type, const std::string& fileName)
110{
111  GLhandleARB shader = 0;
112
113  if (type != ShaderData::Vertex && type != ShaderData::Fragment)
114    return false;
115  this->deleteProgram(type);
116
117
118  std::string program;
119  if (!readShader(fileName, program))
120    return false;
121
122  if (type == ShaderData::Vertex && GLEW_ARB_vertex_shader)
123  {
124    this->vertexShaderFile = fileName;
125
126    shader = this->vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
127  }
128
129  if (type == ShaderData::Fragment && GLEW_ARB_fragment_shader)
130  {
131    this->fragmentShaderFile = fileName;
132
133    shader = this->fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
134  }
135
136  if (shader != 0)
137  {
138    GLint status = 0;
139    const char* prog = program.c_str();
140
141    glShaderSourceARB(shader, 1, &prog, NULL);
142    glCompileShaderARB(shader);
143    // checking on error.
144    glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
145    if (status == GL_INVALID_VALUE || status == GL_INVALID_OPERATION)
146      this->printError(shader);
147    else
148      glAttachObjectARB(this->shaderProgram, shader);
149  }
150  return true;
151}
152
153
154void ShaderData::linkShaderProgram()
155{
156  GLint status = 0;
157
158  glLinkProgramARB(this->shaderProgram);
159  // link error checking
160  glGetObjectParameterivARB(this->shaderProgram, GL_OBJECT_LINK_STATUS_ARB, &status);
161  if (status == GL_INVALID_VALUE || status == GL_INVALID_OPERATION)
162    this->printError(this->shaderProgram);
163}
164
165
166bool ShaderData::readShader(const std::string& fileName, std::string& output)
167{
168  char lineBuffer[PARSELINELENGTH];
169
170  std::ifstream shader;
171  shader.open(fileName.c_str());
172  if (!shader.is_open())
173    return false;
174
175
176  while (!shader.eof())
177  {
178    shader.getline(lineBuffer, PARSELINELENGTH);
179    output += lineBuffer;
180    output += "\n";
181  }
182
183
184  shader.close();
185  return true;
186}
187
188void ShaderData::bindShader(const char* name, const float* value, size_t size)
189{
190  if (likely (this->shaderProgram != 0))
191  {
192    glUseProgramObjectARB(this->shaderProgram);
193
194    unsigned int location = glGetUniformLocationARB(this->shaderProgram, name);
195    /* This is EXPENSIVE and should be avoided. */
196
197    if      (size == 1)  glUniform1fvARB(location, 1, value);
198    else if (size == 2)  glUniform2fvARB(location, 1, value);
199    else if (size == 3)  glUniform3fvARB(location, 1, value);
200    else if (size == 4)  glUniform4fvARB(location, 1, value);
201    else if (size == 9)  glUniformMatrix3fvARB(location, 1, false, value);
202    else if (size == 16) glUniformMatrix4fvARB(location, 1, false, value);
203
204  }
205}
206
207void ShaderData::deleteProgram(ShaderData::Type type)
208{
209  GLint status = 0;
210  if (type == ShaderData::Vertex && this->vertexShader != 0)
211  {
212    this->vertexShaderFile = "";
213    glDetachObjectARB(this->shaderProgram, this->vertexShader);
214    glDeleteObjectARB(this->vertexShader);
215    glGetObjectParameterivARB(this->vertexShader, GL_OBJECT_DELETE_STATUS_ARB, &status);
216    if (status == GL_INVALID_VALUE || status == GL_INVALID_OPERATION)
217      ShaderData::printError(this->vertexShader);
218    this->vertexShader = 0;
219  }
220  else if (type == ShaderData::Fragment && this->fragmentShader != 0)
221  {
222    this->fragmentShaderFile = "";
223    glDetachObjectARB(this->shaderProgram, this->fragmentShader);
224    glDeleteObjectARB(this->fragmentShader);
225    glGetObjectParameterivARB(this->fragmentShader, GL_OBJECT_DELETE_STATUS_ARB, &status);
226    if (status == GL_INVALID_VALUE || status == GL_INVALID_OPERATION)
227      ShaderData::printError(this->fragmentShader);
228    this->fragmentShader = 0;
229  }
230  else
231    return;
232}
233
234
235void ShaderData::printError(GLhandleARB program)
236{
237  if (program == 0)
238    return;
239
240  int infologLength = 0;
241  int charsWritten  = 0;
242  char *infoLog;
243
244  glGetObjectParameterivARB(program, GL_OBJECT_INFO_LOG_LENGTH_ARB,
245                            &infologLength);
246
247  if (infologLength > 0)
248  {
249    infoLog = new char[infologLength+1];
250    glGetInfoLogARB(program, infologLength, &charsWritten, infoLog);
251    printf("%s\n", infoLog);
252    delete[] infoLog;
253  }
254}
255
256void ShaderData::debug() const
257{
258  PRINT(3)("ShaderData info: (SHADER: %d)\n", this->shaderProgram);
259  if (this->vertexShader != 0)
260  {
261    /*    PRINT(3)("VertexShaderProgramm: number=%d, file='%s'\n", this->vertexShader, this->vertexShaderFile);
262        if (this->vertexShaderSource != NULL)
263          for (unsigned int i = 0; i < this->vertexShaderSource->getCount(); i++)
264            PRINT(3)("%d: %s\n", i, this->vertexShaderSource->getEntry(i));
265      }
266      if (this->fragmentShader != 0)
267      {
268        PRINT(3)("FragmentShaderProgramm: number=%d, file='%s'\n", this->fragmentShader, this->fragmentShaderFile);
269        if (this->fragmentShaderSource != NULL)
270          for (unsigned int i = 0; i < this->fragmentShaderSource->getCount(); i++)
271            PRINT(3)("%d: %s\n", i, this->fragmentShaderSource->getEntry(i));*/
272  }
273}
274
Note: See TracBrowser for help on using the repository browser.