rev |
line source |
nuclear@20
|
1 #include <assert.h>
|
nuclear@20
|
2 #include <string>
|
nuclear@20
|
3 #include <map>
|
nuclear@20
|
4 #include "shader.h"
|
nuclear@20
|
5 #include "sdr.h"
|
nuclear@20
|
6 #include "opengl.h"
|
nuclear@20
|
7
|
nuclear@20
|
8 std::map<std::string, unsigned int> sdrdb;
|
nuclear@20
|
9
|
nuclear@20
|
10 SdrProg::SdrProg()
|
nuclear@20
|
11 {
|
nuclear@20
|
12 prog = 0;
|
nuclear@20
|
13 valid = false;
|
nuclear@20
|
14 }
|
nuclear@20
|
15
|
nuclear@20
|
16 SdrProg::~SdrProg()
|
nuclear@20
|
17 {
|
nuclear@20
|
18 destroy();
|
nuclear@20
|
19 }
|
nuclear@20
|
20
|
nuclear@20
|
21 void SdrProg::create()
|
nuclear@20
|
22 {
|
nuclear@20
|
23 destroy();
|
nuclear@20
|
24 prog = glCreateProgram();
|
nuclear@20
|
25 }
|
nuclear@20
|
26
|
nuclear@20
|
27 void SdrProg::destroy()
|
nuclear@20
|
28 {
|
nuclear@20
|
29 if(prog) {
|
nuclear@20
|
30 glDeleteProgram(prog);
|
nuclear@20
|
31 }
|
nuclear@20
|
32 valid = false;
|
nuclear@20
|
33
|
nuclear@20
|
34 for(size_t i=0; i<priv_sdr.size(); i++) {
|
nuclear@20
|
35 glDeleteShader(priv_sdr[i]);
|
nuclear@20
|
36 }
|
nuclear@20
|
37 priv_sdr.clear();
|
nuclear@20
|
38 }
|
nuclear@20
|
39
|
nuclear@20
|
40 bool SdrProg::attach_shader(unsigned int sdr)
|
nuclear@20
|
41 {
|
nuclear@20
|
42 assert(glGetError() == GL_NO_ERROR);
|
nuclear@20
|
43
|
nuclear@20
|
44 glAttachShader(prog, sdr);
|
nuclear@20
|
45 if(glGetError() != GL_NO_ERROR) {
|
nuclear@20
|
46 fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog);
|
nuclear@20
|
47 return false;
|
nuclear@20
|
48 }
|
nuclear@20
|
49
|
nuclear@20
|
50 valid = false;
|
nuclear@20
|
51 return true;
|
nuclear@20
|
52 }
|
nuclear@20
|
53
|
nuclear@20
|
54 bool SdrProg::create(unsigned int vsdr, unsigned int psdr)
|
nuclear@20
|
55 {
|
nuclear@20
|
56 create();
|
nuclear@20
|
57
|
nuclear@20
|
58 if(!attach_shader(vsdr) || !attach_shader(psdr)) {
|
nuclear@20
|
59 return false;
|
nuclear@20
|
60 }
|
nuclear@20
|
61
|
nuclear@20
|
62 if(!link()) {
|
nuclear@20
|
63 return false;
|
nuclear@20
|
64 }
|
nuclear@20
|
65 return true;
|
nuclear@20
|
66 }
|
nuclear@20
|
67
|
nuclear@20
|
68 bool SdrProg::create(const char *vsrc, const char *psrc)
|
nuclear@20
|
69 {
|
nuclear@20
|
70 unsigned int vs = create_shader(vsrc, GL_VERTEX_SHADER);
|
nuclear@20
|
71 if(!vs) {
|
nuclear@20
|
72 return false;
|
nuclear@20
|
73 }
|
nuclear@20
|
74
|
nuclear@20
|
75 unsigned int ps = create_shader(psrc, GL_FRAGMENT_SHADER);
|
nuclear@20
|
76 if(!ps) {
|
nuclear@20
|
77 glDeleteShader(vs);
|
nuclear@20
|
78 return false;
|
nuclear@20
|
79 }
|
nuclear@20
|
80
|
nuclear@20
|
81 if(!create(vs, ps)) {
|
nuclear@20
|
82 glDeleteShader(vs);
|
nuclear@20
|
83 glDeleteShader(ps);
|
nuclear@20
|
84 return false;
|
nuclear@20
|
85 }
|
nuclear@20
|
86
|
nuclear@20
|
87 priv_sdr.push_back(vs);
|
nuclear@20
|
88 priv_sdr.push_back(ps);
|
nuclear@20
|
89 return true;
|
nuclear@20
|
90 }
|
nuclear@20
|
91
|
nuclear@20
|
92 bool SdrProg::load(const char *vfname, const char *pfname)
|
nuclear@20
|
93 {
|
nuclear@20
|
94 unsigned int vs = load_vertex_shader(vfname);
|
nuclear@20
|
95 if(!vs) {
|
nuclear@20
|
96 return false;
|
nuclear@20
|
97 }
|
nuclear@20
|
98 sdrdb[vfname] = vs;
|
nuclear@20
|
99
|
nuclear@20
|
100 unsigned int ps = load_pixel_shader(pfname);
|
nuclear@20
|
101 if(!ps) {
|
nuclear@20
|
102 return false;
|
nuclear@20
|
103 }
|
nuclear@20
|
104 sdrdb[pfname] = ps;
|
nuclear@20
|
105
|
nuclear@20
|
106 printf("creating shader program (%s, %s)\n", vfname, pfname);
|
nuclear@20
|
107 if(!(prog = create_program_link(vs, ps, 0))) {
|
nuclear@20
|
108 return false;
|
nuclear@20
|
109 }
|
nuclear@20
|
110 valid = true;
|
nuclear@20
|
111 return true;
|
nuclear@20
|
112 }
|
nuclear@20
|
113
|
nuclear@20
|
114 bool SdrProg::link() const
|
nuclear@20
|
115 {
|
nuclear@20
|
116 return link_program(prog) != -1;
|
nuclear@20
|
117 }
|
nuclear@20
|
118
|
nuclear@20
|
119 int SdrProg::get_uniform(const char *name) const
|
nuclear@20
|
120 {
|
nuclear@20
|
121 if(!bind()) {
|
nuclear@20
|
122 return -1;
|
nuclear@20
|
123 }
|
nuclear@20
|
124 return glGetUniformLocation(prog, name);
|
nuclear@20
|
125 }
|
nuclear@20
|
126
|
nuclear@20
|
127 int SdrProg::get_attrib(const char *name) const
|
nuclear@20
|
128 {
|
nuclear@20
|
129 if(!bind()) {
|
nuclear@20
|
130 return -1;
|
nuclear@20
|
131 }
|
nuclear@20
|
132 return glGetAttribLocation(prog, name);
|
nuclear@20
|
133 }
|
nuclear@20
|
134
|
nuclear@20
|
135 bool SdrProg::bind_attrib(const char *name, int loc) const
|
nuclear@20
|
136 {
|
nuclear@20
|
137 if(!prog) {
|
nuclear@20
|
138 return false;
|
nuclear@20
|
139 }
|
nuclear@20
|
140
|
nuclear@20
|
141 assert(glGetError() == GL_NO_ERROR);
|
nuclear@20
|
142 glBindAttribLocation(prog, loc, name);
|
nuclear@20
|
143 if(glGetError() != GL_NO_ERROR) {
|
nuclear@20
|
144 fprintf(stderr, "failed to bind attribute %s of program %u to location %d\n",
|
nuclear@20
|
145 name, prog, loc);
|
nuclear@20
|
146 return false;
|
nuclear@20
|
147 }
|
nuclear@20
|
148 valid = false; /* must relink after the glBindAttribLocation call */
|
nuclear@20
|
149 return true;
|
nuclear@20
|
150 }
|
nuclear@20
|
151
|
nuclear@20
|
152 bool SdrProg::bind() const
|
nuclear@20
|
153 {
|
nuclear@20
|
154 if(!prog || (!valid && !link())) {
|
nuclear@20
|
155 return false;
|
nuclear@20
|
156 }
|
nuclear@20
|
157
|
nuclear@20
|
158 assert(glGetError() == GL_NO_ERROR);
|
nuclear@20
|
159 glUseProgram(prog);
|
nuclear@20
|
160 if(glGetError() != GL_NO_ERROR) {
|
nuclear@20
|
161 fprintf(stderr, "failed to bind program %d\n", prog);
|
nuclear@20
|
162 return false;
|
nuclear@20
|
163 }
|
nuclear@20
|
164 return true;
|
nuclear@20
|
165 }
|
nuclear@20
|
166
|
nuclear@20
|
167
|
nuclear@20
|
168 unsigned int get_shader(const char *name, unsigned int type)
|
nuclear@20
|
169 {
|
nuclear@20
|
170 std::map<std::string, unsigned int>::const_iterator it = sdrdb.find(name);
|
nuclear@20
|
171 if(it != sdrdb.end()) {
|
nuclear@20
|
172 return it->second;
|
nuclear@20
|
173 }
|
nuclear@20
|
174
|
nuclear@20
|
175 unsigned int sdr = load_shader(name, type);
|
nuclear@20
|
176 if(!sdr) {
|
nuclear@20
|
177 return 0;
|
nuclear@20
|
178 }
|
nuclear@20
|
179
|
nuclear@20
|
180 sdrdb[name] = sdr;
|
nuclear@20
|
181 return sdr;
|
nuclear@20
|
182 }
|