|
This thread is locked; no one can reply to it. |
1
2
|
A5 - how do I render a quad with a gradient? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Title is the question. Do I draw two primitive triangles? I want to make a horizontal or vertical gradient on a quad, not necessarily an axis aligned bounding box, but maybe an axis aligned trapezoid as well. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
jmasterx
Member #11,410
October 2009
|
I'm not sure but I think https://www.allegro.cc/manual/5/al_draw_prim . I think each vertex defines a color and I think they are linearly interpolated by the graphics card. I have old code to make gradients in GL: 1
2GLuint CGlShape::CreateTexture(std::vector<GLubyte> &pixelData, int width, int height)
3{
4 GLuint texName;
5 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6
7 glGenTextures(1, &texName);
8 glBindTexture(GL_TEXTURE_2D, texName);
9
10
11 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
12 GL_LINEAR);
13 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
14 GL_LINEAR);
15 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width,
16 height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
17 &pixelData[0]);
18
19 return texName;
20}
21
22
23GLuint CGlShape::CreateTextureFromBitmap(wchar_t* filename)
24{
25 Bitmap *b = new Bitmap(filename);
26 if(b == NULL)
27 {
28 return 0;
29 }
30
31 UINT w,h;
32 w = b->GetWidth();
33 h = b->GetHeight();
34 Rect *r = new Rect(0,0,w,h);
35
36
37
38 if(w == 0 && h == 0)
39 {
40 delete(b);
41 return 0;
42 }
43
44 Color c;
45
46 BitmapData bits;
47 b->LockBits(r,ImageLockModeRead,PixelFormat32bppARGB,&bits);
48 delete(r);
49 std::vector<GLubyte> pdata(w * h * 4,0);
50
51 unsigned char *scn;
52 scn = reinterpret_cast<unsigned char*>(bits.Scan0);
53
54 for (unsigned int i = 0; i < h; i++) {
55 for (unsigned int j = 0; j < w; j++) {
56 pdata[i * 4 * w + j * 4 + 0] = (GLubyte) scn[i * 4 * w + j * 4 + 2];
57 pdata[i * 4 * w + j * 4 + 1] = (GLubyte) scn[i * 4 * w + j * 4 + 1];
58 pdata[i * 4 * w + j * 4 + 2] = (GLubyte) scn[i * 4 * w + j * 4 + 0];
59 pdata[i * 4 * w + j * 4 + 3] = (GLubyte) scn[i * 4 * w + j * 4 + 3];
60 }
61 }
62 b->UnlockBits(&bits);
63 delete(b);
64
65 return CreateTexture(pdata,w,h);
66
67}
68
69
70
71
72GLuint CGlShape::CreateGradient(const std::vector<ArgbColorF> &input,vector2f start, vector2f end, size_t width, size_t height,bool radial )
73{
74 std::vector<GLubyte> pdata(width * height * 4);
75 vector2f p0;
76 vector2f p1;
77 vector2f v;
78 vector2f v0;
79
80 float d;
81 float t;
82 p0 = start;
83
84 p1 = end;
85
86 v = p1 - p0;
87
88 float ko = (v.x * v.x) + (v.y * v.y);
89
90 d = sqrt(ko);
91
92 ArgbColorF color;
93 float p;
94 if(!radial) //Linear
95 {
96 v *= (1 / (d * d));
97
98
99
100 for(size_t i = 0; i < height; i++) {
101 for(size_t j = 0; j < width; j++) {
102
103
104 v0.x = j - p0.x;
105 v0.y = i - p0.y;
106
107 t = (v0.x * v.x) + (v0.y * v.y);
108
109 if ((t) < 0)
110 {
111 t = 0;
112 }
113 else if((t) > 1)
114 {
115 t = 1;
116 }
117
118
119
120 //end + start
121
122 for(unsigned int n = 0; n < input.size() - 1; ++n)
123 {
124 if(input[n].percent <= t && input[n + 1].percent >= t)
125 {
126 p = 1 / ((input[n+1].percent - input[n].percent) / (t - input[n].percent));
127
128 color.r = (input[n + 1].r * p) + (input[n].r * (1 - p));
129 color.g = (input[n + 1].g * p) + (input[n].g * (1 - p));
130 color.b = (input[n + 1].b * p) + (input[n].b * (1 - p));
131 color.a = (input[n + 1].a * p) + (input[n].a * (1 - p));
132 }
133 }
134
135
136 pdata[i * 4 * width + j * 4 + 0] = (GLubyte) static_cast<GLubyte>(color.r * 255);
137 pdata[i * 4 * width + j * 4 + 1] = (GLubyte) static_cast<GLubyte>(color.g * 255);
138 pdata[i * 4 * width + j * 4 + 2] = (GLubyte) static_cast<GLubyte>(color.b * 255);
139 pdata[i * 4 * width + j * 4 + 3] = (GLubyte) static_cast<GLubyte>(color.a * 255);
140 }
141 }
142 }
143 else //Radial
144 {
145 for(size_t i = 0; i < height; i++) {
146 for(size_t j = 0; j < width; j++) {
147
148 v0.x = j - p0.x;
149 v0.y = i - p0.y;
150
151 t = (v0.x * v0.x) + (v0.y * v0.y);
152 t = sqrt(t);
153
154 if ((t/d) < 0)
155 {
156 t = 0;
157 }
158 else if((t/d) > 1)
159 {
160 t = 1;
161 }
162 else
163 {
164 t = t/d;
165 }
166
167
168
169 //end + start
170 for(unsigned int n = 0; n < input.size() - 1; ++n)
171 {
172 if(input[n].percent <= t && input[n + 1].percent >= t)
173 {
174 p = 1 / ((input[n+1].percent - input[n].percent) / (t - input[n].percent));
175
176 color.r = (input[n + 1].r * p) + (input[n].r * (1 - p));
177 color.g = (input[n + 1].g * p) + (input[n].g * (1 - p));
178 color.b = (input[n + 1].b * p) + (input[n].b * (1 - p));
179 color.a = (input[n + 1].a * p) + (input[n].a * (1 - p));
180 }
181 }
182 pdata[i * 4 * width + j * 4 + 0] = (GLubyte) static_cast<GLubyte>(color.r * 255);
183 pdata[i * 4 * width + j * 4 + 1] = (GLubyte) static_cast<GLubyte>(color.g * 255);
184 pdata[i * 4 * width + j * 4 + 2] = (GLubyte) static_cast<GLubyte>(color.b * 255);
185 pdata[i * 4 * width + j * 4 + 3] = (GLubyte) static_cast<GLubyte>(color.a * 255);
186 }
187 }
188
189 }
190
191 return CreateTexture(pdata,width,height);
192}
193
194
195
196
197
198
199
200
201GLuint CGlShape::CreateAngularGradient(const std::vector<ArgbColorF> &input,vector2f start, vector2f end, size_t width, size_t height )
202{
203 std::vector<GLubyte> pdata(width * height * 4);
204
205 float cx;
206 float cy;
207
208 float r1;
209 float r2;
210 float ang;
211
212 float t;
213 float p;
214
215 cx = start.x;
216 cy = start.y;
217 end -= 500;
218
219 r1 = 0;
220 r2 = GetDistance(static_cast<float>(cx),static_cast<float>(cy),
221 static_cast<float>(width * height)
222 ,static_cast<float>(width * height));
223
224 ang = atan2(-end.y - start.y,end.x - start.x) + pi;
225
226 ArgbColorF color;
227
228 for(size_t i = 0; i < height; i++) {
229 for(size_t j = 0; j < width; j++) {
230
231 t= atan2(i-cy,j-cx) + ang;
232 t= t+ pi;
233 if (t > 2* pi)
234 {
235 t=t-2*pi;
236
237 }
238
239 t=t/(2*pi);
240
241 //end + start
242 for(unsigned int n = 0; n < input.size() - 1; ++n)
243 {
244 if(input[n].percent <= t && input[n + 1].percent >= t)
245 {
246 p = 1 / ((input[n+1].percent - input[n].percent) / (t - input[n].percent));
247
248 color.r = (input[n + 1].r * p) + (input[n].r * (1 - p));
249 color.g = (input[n + 1].g * p) + (input[n].g * (1 - p));
250 color.b = (input[n + 1].b * p) + (input[n].b * (1 - p));
251 color.a = (input[n + 1].a * p) + (input[n].a * (1 - p));
252 }
253 }
254
255 pdata[i * 4 * width + j * 4 + 0] = (GLubyte) static_cast<GLubyte>(color.r * 255);
256 pdata[i * 4 * width + j * 4 + 1] = (GLubyte) static_cast<GLubyte>(color.g * 255);
257 pdata[i * 4 * width + j * 4 + 2] = (GLubyte) static_cast<GLubyte>(color.b * 255);
258 pdata[i * 4 * width + j * 4 + 3] = (GLubyte) static_cast<GLubyte>(color.a * 255);
259 }
260 }
261
262 return CreateTexture(pdata,width,height);
263}
Agui GUI API -> https://github.com/jmasterx/Agui |
Edgar Reynaldo
Major Reynaldo
May 2007
|
A5 doesn't support QUADS directly with al_draw_prim yet... hence the question, do I render two primitive triangles? The opposing corners of the quad won't be interpolated correctly because not all 4 corners is being taken into account at a time for mixing the color. IDK what to do... My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
jmasterx
Member #11,410
October 2009
|
Then the only thing I can think of is to generate the gradients using something like the code above and texture map the UVs yourself. Agui GUI API -> https://github.com/jmasterx/Agui |
Arthur Kalliokoski
Second in Command
February 2005
|
I'm pretty sure video drivers break the quads down into triangles anyway, so yeah, use a texture. They all watch too much MSNBC... they get ideas. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
How can I use a texture if I don't have a way to render it? You mean use a primitive? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
jmasterx
Member #11,410
October 2009
|
int al_draw_prim(const void* vtxs, const ALLEGRO_VERTEX_DECL* decl, It has a texture parameter. Agui GUI API -> https://github.com/jmasterx/Agui |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Arg, you guys don't get it. I don't want to use a texture, I want to render a gradient quad. I know al_draw_prim can take a texture and map it to a triangle. I need to be able to draw gradient rectangles on the fly, for several reasons. If I have to I can emulate it all with a bunch of filled rectangles but that sucks. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Arthur Kalliokoski
Second in Command
February 2005
|
Colored triangles normally use Goraud shading, which won't draw evenly across the long leg of a pair of triangles. Maybe you could use a shader program? They all watch too much MSNBC... they get ideas. |
jmasterx
Member #11,410
October 2009
|
Yeah, a fragment shader should consider a trapezoid or quad as a single fragment and from there you have per-pixel freedom to do any kind of gradient rather easily. Agui GUI API -> https://github.com/jmasterx/Agui |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Hmm, had not planned on doing this with shaders - it's just supposed to be part of the basic graphics api. Well here's what it looks like - can't really tell it is two triangles. Get's all funky when you try to vary the vertex colors though : My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Trent Gamblin
Member #261
April 2000
|
I don't get it. Why can't two triangles be drawn with a gradient? You give 6 vertices a color in all, 2 pairs share the same color.
|
kazzmir
Member #1,786
December 2001
|
Can you just copy the primitive code for drawing a rectangle and changing the colors for the verticies? 1void al_draw_filled_rectangle(float x1, float y1, float x2, float y2,
2 ALLEGRO_COLOR color)
3{
4 ALLEGRO_VERTEX vtx[4];
5 int ii;
6
7 vtx[0].x = x1; vtx[0].y = y1;
8 vtx[1].x = x1; vtx[1].y = y2;
9 vtx[2].x = x2; vtx[2].y = y2;
10 vtx[3].x = x2; vtx[3].y = y1;
11
12 for (ii = 0; ii < 4; ii++) {
13 vtx[ii].color = color;
14 vtx[ii].z = 0;
15 }
16
17 al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN);
18}
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Trent Gamblin said: I don't get it. Why can't two triangles be drawn with a gradient? You give 6 vertices a color in all, 2 pairs share the same color. That's what I did though, and those are the results in the third picture. I need it to draw evenly between the four corners, but what it is doing now works for strictly horizontal and vertical gradients so I don't really care. @Kazzmir ALLEGRO_VERTEX t1[3] = {vtx[0] , vtx[1] , vtx[2]}; ALLEGRO_VERTEX t2[3] = {vtx[0] , vtx[2] , vtx[3]}; al_draw_prim(t1 , 0 , 0 , 0 , 3 , ALLEGRO_PRIM_TRIANGLE_LIST); al_draw_prim(t2 , 0 , 0 , 0 , 3 , ALLEGRO_PRIM_TRIANGLE_LIST); But yeah, maybe a TRIANGLE_FAN would work too. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Trent Gamblin
Member #261
April 2000
|
Can you show a picture of how it's supposed to look?
|
kazzmir
Member #1,786
December 2001
|
Should it look something like this? {"name":"607131","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac53c813f678eaf9b1a3ee6aed22a218.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac53c813f678eaf9b1a3ee6aed22a218"} 1void shaded(float x1, float y1, float x2, float y2,
2 ALLEGRO_COLOR color1, ALLEGRO_COLOR color2,
3 ALLEGRO_COLOR color3, ALLEGRO_COLOR color4){
4 ALLEGRO_VERTEX vtx[4];
5 int ii;
6
7 vtx[0].x = x1; vtx[0].y = y1;
8 vtx[1].x = x1; vtx[1].y = y2;
9 vtx[2].x = x2; vtx[2].y = y2;
10 vtx[3].x = x2; vtx[3].y = y1;
11
12 for (ii = 0; ii < 4; ii++) {
13 vtx[ii].z = 0;
14 }
15 vtx[0].color = color1;
16 vtx[1].color = color2;
17 vtx[2].color = color3;
18 vtx[3].color = color4;
19
20 al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN);
21}
22
23shaded(100, 100, 400, 400,
24 al_map_rgb(255, 0, 0),
25 al_map_rgb(128, 128, 0),
26 al_map_rgb(0, 255, 0),
27 al_map_rgb(128, 128, 0));
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
{"name":"607132","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/2\/924e92393b84f843790638562d63c808.png","w":812,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/2\/924e92393b84f843790638562d63c808"} 1
2
3
4#include <allegro.h>
5
6
7//void quad3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3, *v4);
8
9
10V3D_f MakeVertex(float x , float y , float z , float u , float v , int c) {
11 V3D_f vtx;
12 vtx.x = x;
13 vtx.y = y;
14 vtx.z = z;
15 vtx.u = u;
16 vtx.v = v;
17 vtx.c = c;
18 return vtx;
19}
20
21void quad(BITMAP* bmp , float x1 , float y1 , int c1 ,
22 float x2 , float y2 , int c2 ,
23 float x3 , float y3 , int c3 ,
24 float x4 , float y4 , int c4) {
25 V3D_f v3d[4] = {
26 MakeVertex(x1 , y1 , 0.0 , 0.0 , 0.0 , c1),
27 MakeVertex(x2 , y2 , 0.0 , 0.0 , 0.0 , c2),
28 MakeVertex(x3 , y3 , 0.0 , 0.0 , 0.0 , c3),
29 MakeVertex(x4 , y4 , 0.0 , 0.0 , 0.0 , c4)
30 };
31
32 quad3d_f(bmp , POLYTYPE_GCOL , 0 , &v3d[0] , &v3d[1] , &v3d[2] , &v3d[3]);
33}
34
35int main(int argc , char** argv) {
36
37 if (allegro_init() != 0) {
38 return 1;
39 }
40 install_keyboard();
41
42 set_color_depth(desktop_color_depth());
43 if (set_gfx_mode(GFX_AUTODETECT_WINDOWED , 800 , 600 , 0 , 0) != 0) {
44 return 1;
45 }
46
47
48 int blue = makecol(0,0,255);
49 int black = makecol(0,0,0);
50 int white = makecol(255,255,255);
51 int red = makecol(255,0,0);
52 int green = makecol(0,255,0);
53
54 clear_to_color(screen , blue);
55 quad(screen , 150 , 150 , black ,
56 800 , 150 , white ,
57 600 , 450 , black ,
58 0 , 450 , white);
59 readkey();
60
61 return 0;
62}
63END_OF_MAIN()
Ah, this one looks good too. If I was doing this with two triangle primitives it would have a seam in it I think. Test that tomorrow. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Trent Gamblin
Member #261
April 2000
|
The opengl spec specifies that if two triangles share vertices there will be no seem. I don't see a seam in the picture you say is wrong either. If you want non-linear shading you'll have to use shaders, simple as that.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Look at the difference between these two. A5 with al_draw_prim : A4 with quad3d_f : In the first there is a very bright white seam. In the second the middle is gray. The second is what I want. Is that possible with A5? I used POLYTYPE_GCOL for gouraud shading on the a4 polygon. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Arthur Kalliokoski
Second in Command
February 2005
|
Look at your quad_3df image and draw an imaginary line between two opposing vertices, and tell me how Goraud interpolation is supposed to handle going brighter to dimmer to brighter or vice versa. I still say use a texture, GPU's have enough hardware to handle it in parallel so no slowdown should be apparent. They all watch too much MSNBC... they get ideas. |
SiegeLord
Member #7,827
October 2006
|
Edgar Reynaldo said: Is that possible with A5?
Trent Gamblin said: If you want non-linear shading you'll have to use shaders, simple as that. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
EWClay
Member #14,750
December 2012
|
How about an extra vertex at the centre of the quad, using a colour which is the average of the four corners? Can't guarantee it won't still show seams, but it should be closer to what you want. |
Elias
Member #358
May 2000
|
Would have a cross-shaped seam then. The solution should be to write a shader which does what A4 does, which probably is this: [1] -- |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Arthur Kalliokoski said: tell me how Goraud interpolation is supposed to handle going brighter to dimmer to brighter or vice versa. I don't even know what gouraud means. All I'm looking for is an even distribution between the four corners somehow. :/ EWClay said: How about an extra vertex at the centre of the quad, using a colour which is the average of the four corners?
Elias said: Would have a cross-shaped seam then. I was thinking of that idea as well. Perhaps A4 is merely rendering 4 triangles instead of the two I was thinking of. I will look at this later. Elias said: The solution should be to write a shader which does what A4 does, which probably is this: [1] Not sure what I'm looking at there. What does it do different than A5? SiegeLord said: Use shaders... Are there shader tutorials out there somewhere? Because I don't really know how to use them right or at all. :/ My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
jmasterx
Member #11,410
October 2009
|
Fragment shaders are pretty straight forward, especially for your needs. The way they work is that the shader is called per-fragment, so for example, a quad might be a fragment. The fragment will get rasterized into pixels. The shader will run for each pixel. You will also get information like relatively where you are on the bitmap. The values are either -1.0 to 1.0 or 0.0 to 1.0 I forget. But essentially by knowing that, you can linearly interpolate 2 colors or more. Shaders also need a vertex component. Which is pretty straight forward. Just multiply the view matrix by the vertex position in the 2D case. Here is my class for wrapping the shader addon. HPP 1#ifndef CGE_SHADER_HPP
2#define CGE_SHADER_HPP
3#include <string>
4#include "Game/platform.hpp"
5#include "Agui/Image.hpp"
6#include "Game/Resource/Sprite.hpp"
7namespace cge
8{
9 class Shader
10 {
11 public:
12 ~Shader();
13 Shader();
14 Shader( const std::string & vtxsrcpath, const std::string & pxsrcpath);
15 bool load( const std::string & vtxsrcpath, const std::string & pxsrcpath);
16 void use();
17 void stop();
18 bool setSampler(agui::Image* img, const std::string& name, int unit = 0);
19 bool setSampler(Sprite* img, const std::string& name, int unit = 0);
20 bool setSampler(ALLEGRO_BITMAP* img, const std::string& name, int unit = 0);
21 void destroy();
22 void printLog();
23 ALLEGRO_SHADER* getShader();
24 void setVal(const std::string& name, float val);
25 void setVal(const std::string& name, int val);
26 void setVal(const std::string& name, bool val);
27 static Shader& getDefaultShader();
28 bool isDefaultShader();
29 void mountShader();
30 static void setGlsl(bool glsl);
31 static bool isGlsl();
32 static bool isHlsl();
33 private:
34 void create();
35 bool loadSource(const std::string & srcpath, bool pixelShader);
36 bool link();
37 static bool m_glsl;
38 ALLEGRO_SHADER* m_shader;
39 std::string m_src;
40 static Shader m_default;
41 bool m_inUse;
42 };
43}
44
45#endif
CPP 1#include "Game/Shader/Shader.hpp"
2#include "Agui/Backends/Allegro5/Allegro5Image.hpp"
3#include <allegro5/allegro_shader_hlsl.h>
4#include <allegro5/allegro_shader_glsl.h>
5#include <iostream>
6#ifdef _WIN32
7#include <allegro5/allegro_windows.h>
8#include <allegro5/allegro_direct3d.h>
9#include <allegro5/allegro_shader_hlsl.h>
10#endif
11
12namespace cge
13{
14
15 void Shader::destroy()
16 {
17 if(m_shader)
18 {
19 if(!isDefaultShader() && m_inUse)
20 {
21 stop();
22 }
23 al_destroy_shader(m_shader);
24 m_shader = NULL;
25 }
26 }
27
28 void Shader::create()
29 {
30 destroy();
31 m_shader = al_create_shader(isGlsl() ? ALLEGRO_SHADER_GLSL : ALLEGRO_SHADER_HLSL);
32
33 }
34
35 bool Shader::loadSource( const std::string & srcpath, bool pixelShader )
36 {
37 return al_attach_shader_source_file(m_shader,
38 pixelShader ? ALLEGRO_PIXEL_SHADER : ALLEGRO_VERTEX_SHADER,srcpath.c_str());
39 }
40
41 Shader::Shader()
42 : m_shader(NULL),m_inUse(false)
43 {
44
45 }
46
47 Shader::Shader( const std::string & vtxsrcpath, const std::string & pxsrcpath)
48 : m_shader(NULL),m_inUse(false)
49 {
50 load(vtxsrcpath,pxsrcpath);
51 }
52
53 bool Shader::link()
54 {
55 return al_link_shader(m_shader);
56 }
57
58 bool Shader::load( const std::string & vtxsrcpath, const std::string & pxsrcpath)
59 {
60 std::string appendV = isHlsl() ? ".hlslv" : ".glslv";
61 std::string appendP = isHlsl() ? ".hlslp" : ".glslp";
62
63 create();
64 if(!m_shader)
65 {
66 std::cout << "create fail\n";
67 return false;
68 }
69
70 if(vtxsrcpath != "")
71 {
72 if(!loadSource(vtxsrcpath + appendV,false))
73 {
74 std::cout << "vtx src load fail\n";
75 fprintf(stderr, "%s\n", al_get_shader_log(m_shader));
76 return false;
77 }
78 }
79
80 if(pxsrcpath != "")
81 {
82 if(!loadSource(pxsrcpath + appendP,true))
83 {
84 std::cout << "px src load fail\n";
85 fprintf(stderr, "%s\n", al_get_shader_log(m_shader));
86 return false;
87 }
88 }
89
90 if(!link())
91 {
92 std::cout << "link fail\n";
93 return false;
94 }
95
96 std::cout << "success\n";
97
98 if(isDefaultShader())
99 {
100 use();
101 }
102 return true;
103 }
104
105 void Shader::use()
106 {
107 m_inUse = true;
108 mountShader();
109 al_use_shader(m_shader,true);
110 }
111
112 void Shader::stop()
113 {
114 al_use_shader(m_shader,false);
115 if(!isDefaultShader())
116 {
117 getDefaultShader().use();
118 }
119 }
120
121 bool Shader::setSampler( agui::Image* img, const std::string& name, int unit /*= 0*/ )
122 {
123 return al_set_shader_sampler(m_shader,name.c_str(),((agui::Allegro5Image*)img)->getBitmap(),unit);
124 }
125
126 bool Shader::setSampler( Sprite* img, const std::string& name, int unit /*= 0*/ )
127 {
128 return al_set_shader_sampler(m_shader,name.c_str(),img->getBitmap(),unit);
129 }
130
131 bool Shader::setSampler( ALLEGRO_BITMAP* img, const std::string& name, int unit /*= 0*/ )
132 {
133 return al_set_shader_sampler(m_shader,name.c_str(),img,unit);
134 }
135
136 Shader::~Shader()
137 {
138
139 destroy();
140
141 }
142
143 ALLEGRO_SHADER* Shader::getShader()
144 {
145 return m_shader;
146 }
147
148 void Shader::setVal( const std::string& name, float val )
149 {
150 al_set_shader_float(m_shader,name.c_str(),val);
151 }
152
153 void Shader::setVal( const std::string& name, int val )
154 {
155 al_set_shader_int(m_shader,name.c_str(),val);
156 }
157
158 void Shader::setVal( const std::string& name, bool val )
159 {
160 al_set_shader_bool(m_shader,name.c_str(),val);
161 }
162
163 void Shader::printLog()
164 {
165 std::cout << al_get_shader_log(m_shader) << "\n";
166 }
167
168 Shader& Shader::getDefaultShader()
169 {
170 return m_default;
171 }
172
173 bool Shader::isDefaultShader()
174 {
175 return this == &getDefaultShader();
176 }
177
178 void Shader::mountShader()
179 {
180 if(isHlsl())
181 al_set_direct3d_effect(al_get_current_display(), al_get_direct3d_effect(getShader()));
182 else
183 al_set_opengl_program_object(al_get_current_display(), al_get_opengl_program_object(getShader()));
184 }
185
186 void Shader::setGlsl( bool glsl )
187 {
188 m_glsl = glsl;
189 }
190
191 bool Shader::isGlsl()
192 {
193 return m_glsl;
194 }
195
196 bool Shader::isHlsl()
197 {
198 return !isGlsl();
199 }
200
201 bool Shader::m_glsl(false);
202
203 cge::Shader Shader::m_default;
204
205}
Here is the vertex shader I use (hlsl): 1 struct VS_INPUT
2 {
3 float4 Position : POSITION0;
4 float2 TexCoord : TEXCOORD0;
5 float4 Color : TEXCOORD1;
6 };
7 struct VS_OUTPUT
8 {
9 float4 Position : POSITION0;
10 float4 Color : COLOR0;
11 float2 TexCoord : TEXCOORD0;
12 };
13
14 float4x4 projview_matrix;
15
16 VS_OUTPUT vs_main(VS_INPUT Input)
17 {
18 VS_OUTPUT Output;
19 Output.Position = mul(Input.Position, projview_matrix);
20 Output.Color = Input.Color;
21 Output.TexCoord = Input.TexCoord;
22 return Output;
23 }
Agui GUI API -> https://github.com/jmasterx/Agui |
|
1
2
|