rev |
line source |
nuclear@5
|
1 #include <string.h>
|
nuclear@3
|
2 #include <GL/glew.h>
|
nuclear@5
|
3 #include <imago2.h>
|
nuclear@3
|
4 #include "material.h"
|
nuclear@3
|
5
|
nuclear@5
|
6 static const char *find_path(const char *fname);
|
nuclear@5
|
7
|
nuclear@3
|
8 Material::Material()
|
nuclear@4
|
9 : diffuse(1, 1, 1), specular(0, 0, 0)
|
nuclear@3
|
10 {
|
nuclear@3
|
11 shininess = 1.0;
|
nuclear@3
|
12 alpha = 1.0;
|
nuclear@5
|
13
|
nuclear@5
|
14 for(int i=0; i<NUM_TEXTURES; i++) {
|
nuclear@5
|
15 tex[i] = 0;
|
nuclear@5
|
16 tex_scale[i].x = tex_scale[i].y = 1.0f;
|
nuclear@5
|
17 }
|
nuclear@5
|
18 sdr = 0;
|
nuclear@3
|
19 }
|
nuclear@3
|
20
|
nuclear@3
|
21 void Material::setup() const
|
nuclear@3
|
22 {
|
nuclear@4
|
23 float col[] = {diffuse.x, diffuse.y, diffuse.z, alpha};
|
nuclear@3
|
24 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
|
nuclear@3
|
25
|
nuclear@3
|
26 float spec[] = {specular.x, specular.y, specular.z, 1.0};
|
nuclear@3
|
27 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
|
nuclear@3
|
28
|
nuclear@3
|
29 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess > 128 ? 128 : shininess);
|
nuclear@5
|
30
|
nuclear@5
|
31 if(sdr) {
|
nuclear@5
|
32 glUseProgram(sdr);
|
nuclear@5
|
33 }
|
nuclear@5
|
34
|
nuclear@5
|
35 if(tex[TEX_DIFFUSE]) {
|
nuclear@5
|
36 glActiveTexture(GL_TEXTURE0);
|
nuclear@5
|
37
|
nuclear@5
|
38 glMatrixMode(GL_TEXTURE);
|
nuclear@5
|
39 glLoadIdentity();
|
nuclear@5
|
40 glTranslatef(tex_offset[TEX_DIFFUSE].x, tex_offset[TEX_DIFFUSE].y, 0);
|
nuclear@5
|
41 glScalef(tex_scale[TEX_DIFFUSE].x, tex_scale[TEX_DIFFUSE].y, 1);
|
nuclear@5
|
42
|
nuclear@5
|
43 glBindTexture(GL_TEXTURE_2D, tex[TEX_DIFFUSE]);
|
nuclear@5
|
44 glEnable(GL_TEXTURE_2D);
|
nuclear@5
|
45
|
nuclear@5
|
46 int loc = glGetUniformLocation(sdr, "tex_diffuse");
|
nuclear@5
|
47 if(loc != -1) {
|
nuclear@5
|
48 glUniform1i(loc, 0);
|
nuclear@5
|
49 }
|
nuclear@5
|
50 }
|
nuclear@5
|
51 if(tex[TEX_ENVMAP]) {
|
nuclear@5
|
52 glActiveTexture(GL_TEXTURE1);
|
nuclear@5
|
53
|
nuclear@5
|
54 glMatrixMode(GL_TEXTURE);
|
nuclear@5
|
55 glLoadIdentity();
|
nuclear@5
|
56 glTranslatef(tex_offset[TEX_ENVMAP].x, tex_offset[TEX_ENVMAP].y, 0);
|
nuclear@5
|
57 glScalef(tex_scale[TEX_ENVMAP].x, tex_scale[TEX_ENVMAP].y, 1);
|
nuclear@5
|
58
|
nuclear@5
|
59 glBindTexture(GL_TEXTURE_2D, tex[TEX_ENVMAP]);
|
nuclear@5
|
60 glEnable(GL_TEXTURE_2D);
|
nuclear@5
|
61
|
nuclear@5
|
62 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
nuclear@5
|
63 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
nuclear@5
|
64 glEnable(GL_TEXTURE_GEN_S);
|
nuclear@5
|
65 glEnable(GL_TEXTURE_GEN_T);
|
nuclear@5
|
66
|
nuclear@5
|
67 int loc = glGetUniformLocation(sdr, "tex_envmap");
|
nuclear@5
|
68 if(loc != -1) {
|
nuclear@5
|
69 glUniform1i(loc, 1);
|
nuclear@5
|
70 }
|
nuclear@5
|
71 }
|
nuclear@5
|
72
|
nuclear@5
|
73 glActiveTexture(GL_TEXTURE0);
|
nuclear@5
|
74 glMatrixMode(GL_MODELVIEW);
|
nuclear@3
|
75 }
|
nuclear@5
|
76
|
nuclear@5
|
77 unsigned int load_texture(const char *fname)
|
nuclear@5
|
78 {
|
nuclear@5
|
79 int xsz, ysz;
|
nuclear@5
|
80 void *pixels;
|
nuclear@5
|
81 unsigned int tex;
|
nuclear@5
|
82
|
nuclear@5
|
83 const char *path = find_path(fname);
|
nuclear@5
|
84
|
nuclear@5
|
85 if(!(pixels = img_load_pixels(path, &xsz, &ysz, IMG_FMT_RGBA32))) {
|
nuclear@5
|
86 fprintf(stderr, "failed to load texture: %s\n", fname);
|
nuclear@5
|
87 return 0;
|
nuclear@5
|
88 }
|
nuclear@5
|
89
|
nuclear@5
|
90 glGenTextures(1, &tex);
|
nuclear@5
|
91 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@5
|
92 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@5
|
93 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@5
|
94 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
nuclear@5
|
95 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
nuclear@5
|
96 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
nuclear@5
|
97 img_free_pixels(pixels);
|
nuclear@5
|
98 return tex;
|
nuclear@5
|
99 }
|
nuclear@5
|
100
|
nuclear@5
|
101 static char *read_shader(const char *fname)
|
nuclear@5
|
102 {
|
nuclear@5
|
103 FILE *fp = fopen(fname, "r");
|
nuclear@5
|
104 if(!fp) {
|
nuclear@5
|
105 return 0;
|
nuclear@5
|
106 }
|
nuclear@5
|
107 fseek(fp, 0, SEEK_END);
|
nuclear@5
|
108 long len = ftell();
|
nuclear@5
|
109 rewind(fp);
|
nuclear@5
|
110
|
nuclear@5
|
111 char *buf = new char[len + 1];
|
nuclear@5
|
112 fread(buf, len, fp);
|
nuclear@5
|
113 buf[len] = 0;
|
nuclear@5
|
114 fclose(fp);
|
nuclear@5
|
115
|
nuclear@5
|
116 return buf;
|
nuclear@5
|
117 }
|
nuclear@5
|
118
|
nuclear@5
|
119 unsigned int load_shader_program(const char *vname, const char *pname)
|
nuclear@5
|
120 {
|
nuclear@5
|
121 unsigned int vsdr = 0, psdr = 0;
|
nuclear@5
|
122
|
nuclear@5
|
123 if(vname) {
|
nuclear@5
|
124 char *src = read_shader(find_path(vname));
|
nuclear@5
|
125 if(!src) {
|
nuclear@5
|
126 fprintf(stderr, "failed to load vertex shader: %s\n", vname);
|
nuclear@5
|
127 return 0;
|
nuclear@5
|
128 }
|
nuclear@5
|
129 vsdr = glCreateShader(GL_VERTEX_SHADER);
|
nuclear@5
|
130 glShaderSource(vsdr, 1, &src, 0);
|
nuclear@5
|
131 delete [] src;
|
nuclear@5
|
132
|
nuclear@5
|
133 int res;
|
nuclear@5
|
134 glGetShaderiv(vsdr, GL_INFO_LOG_LENGTH, &res);
|
nuclear@5
|
135 if(res > 0) {URE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
nuclear@5
|
136 img_free_pixels(pixels);
|
nuclear@5
|
137 return tex;
|
nuclear@5
|
138 }
|
nuclear@5
|
139
|
nuclear@5
|
140 static char *read_shader(const char *fname)
|
nuclear@5
|
141 {
|
nuclear@5
|
142 FILE *fp = fopen(find_path(vname), "r");
|
nuclear@5
|
143 if(!fp) {
|
nuclear@5
|
144 fprintf(stderr, "failed to load shader: %s\n", vname);
|
nuclear@5
|
145 return 0;
|
nuclear@5
|
146 char *info = new char[res];
|
nuclear@5
|
147 glGetShaderInfoLog(vsdr, res, &res, info);
|
nuclear@5
|
148 printf("shader compiler log: %s\n", info);
|
nuclear@5
|
149 }
|
nuclear@5
|
150 glGetShaderiv(vsdr, GL_COMPILE_STATUS, &res);
|
nuclear@5
|
151 if(!res) {
|
nuclear@5
|
152 return 0;
|
nuclear@5
|
153 }
|
nuclear@5
|
154 }
|
nuclear@5
|
155 }
|
nuclear@5
|
156
|
nuclear@5
|
157 static const char *find_path(const char *fname)
|
nuclear@5
|
158 {
|
nuclear@5
|
159 const char *ptr = fname + strlen(fname) - 1;
|
nuclear@5
|
160
|
nuclear@5
|
161 do {
|
nuclear@5
|
162 while(*ptr != '/' && ptr > fname - 1) {
|
nuclear@5
|
163 ptr--;
|
nuclear@5
|
164 }
|
nuclear@5
|
165
|
nuclear@5
|
166 FILE *fp = fopen(ptr + 1, "rb");
|
nuclear@5
|
167 if(fp) {
|
nuclear@5
|
168 fclose(fp);
|
nuclear@5
|
169 return ptr + 1;
|
nuclear@5
|
170 }
|
nuclear@5
|
171 ptr -= 1;
|
nuclear@5
|
172
|
nuclear@5
|
173 } while(ptr >= fname);
|
nuclear@5
|
174
|
nuclear@5
|
175 return fname;
|
nuclear@5
|
176 }
|