Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/graphics/shader_data.cc @ 9818

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

Switching to new Shader layout, with Shader and ShaderData. Shaders do not render for the time being

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