I have some problems with OpenGL and luminosity. Let me explain you my problem :
I drew this "sprite" (it's only a plane here) with a code like that :
sprite.set_active
left, right, top, bottom = 0.0, 1.0, 1.0, 0.0
glPushMatrix
glTranslate(#position.x - 16, #position.y, #position.z)
glRotate(-90 -#window.camera.horizontal_angle, 0, 1, 0)
glScale(chara.width, chara.height, 32.0)
begin
glEnable(GL_BLEND)
glBegin(GL_QUADS)
glColor4f(1.0, 1.0, 1.0, 1.0)
glTexCoord2d(left, top); glVertex3f(0, 1, 0.5)
glTexCoord2d(right, top); glVertex3f(1, 1, 0.5)
glTexCoord2d(right, bottom); glVertex3f(1, 0, 0.5)
glTexCoord2d(left, bottom); glVertex3f(0, 0, 0.5)
glEnd
glDisable(GL_BLEND)
rescue
end
glPopMatrix
My problem is with that line :
glColor4f(1.0, 1.0, 1.0, 1.0)
Well, I can put a number lesser than 1.0 to have a darker sprite, but I can't do the contrary. How can I do that ? How can I make the sprite be totally white, for example ?
To get full control over your fragment processing, the best approach is using the programmable pipeline, where you can implement exactly what you want with GLSL code.
But there are some options that could work for this case in the fixed pipeline. The simplest one is using a different GL_TEXTURE_ENV_MODE. The default value is GL_MODULATE, which means that the color you specified with glColor4f() is multiplied with the color from the texture. As you found, that allows you to make the texture darker, but not brighter.
You could try using GL_ADD instead. As the name suggests, this will produce the final output as the sum of the texture color and the color from glColor4f(). For example:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
glColor4f(0.2f, 0.2f, 0.2f, 0.0f);
would add 0.2 to the color components read from the texture.
There is more complex functionality in the fixed pipeline that gives you more control over how texture values are used to generate colors. You can find it by looking for "texture combiners". But in my personal opinion, you're much better off moving to the programmable pipeline if you need something complex enough to require texture combiners.
Related
I have drawn a rectangle, which spins. Also I have set the texture for it, but it does look like very ugly (very low resolution).
The table of vertex for rectangle is the next:
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
This is the coordinates for the texture mapping the above rectangle:
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
The size of texture is 512x512 (it's too large!!!, so there mustn't be such problems with the size exactly).
The full source code locates here:
http://pastebin.com/qXJFNe1c
I clearly understand, that is my fault, but I don't get where exactly is the fault.
PS
I think, that such a problem isn't related strongly to WebGL, I think that some pure OpenGL developers could give me a piece of advice also.
If you want to test it live, you may check it via:
http://goo.gl/YpXyPl
When testing, [.WebGLRenderingContext]RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete' 77.246.234.123:8893/plane/:1, but it does render a texture at least, so maybe that's about something else.
Also the viewport seems to be 300 x 150. The canvas rendering width/height does not match the width/height within the html page. Try this:
function updateCanvasSize(canvas)
{
if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight)
{
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
//might want to update the projection matrix to fix the new aspect ratio too
}
}
and in the a draw or update function (I doubt this would impact performance)...
var canvas = document.getElementById("canvas-main"); //or store "canvas" globally
updateCanvasSize(canvas);
The incorrect canvas size occurs because at the time webGLStart is called, the canvas is actually 300x150 for whatever reason. Either 1. You actually want a fixed size render target (give the canvas widht/height in pixels and all is well) or 2. you want it to take up the whole window, in which case the user may want to resize the window which needs to be handled (js probably has a resize event you could use too instead of polling).
I am trying to create a VBO for a simple rectangle. The GL is set up to use the core profile (GL: 3.2, GLSL: 1.5, inside an NSView in Cocoa).
I spent hours trying to figure out how to draw a simple rectangle in OpenGL. It seems really hard to find any decent tutorials on the core profile. The best I could find was this tutorial.
I adapted it to my needs and came up with the following code:
GLfloat vertices[] = { 1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0 };
glGenBuffers(1, &vertexVBO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*4, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(VERTEX_POS, 3, GL_FLOAT, GL_FALSE, 0, 0); // VERTEX_POS = 0
glEnableVertexAttribArray(VERTEX_POS); // fails
However, this is throwing an error when calling glEnableVertexAttribArray: INVALID_OPERATION. The documentation suggests that this error is produced if the aforementioned call is made between a glBegin and glEnd. This is not the case. I mean, as far as I know, glBegin and glEnd are not even supported in the core profile.
Thus, I am at a loss. How can I draw this stupid rectangle (or at least initialize it)?
You need to bind a VAO before setting attribute pointers.
GLuint vao_name;
glGenVertexArrays(1, &vao_name);
glBindVertexArray(vao_name);
// ...
glVertexAttribPointer(...);
glEnableVertexAttribArray(...);
Also, the documentation you're linking to is outdated — use this one instead.
Imagine you're standing on the ground looking up at a cube in the sky. As you tilt your head, the cube moves. I'm trying to replicate this using OpenGL ES on the iPhone by manipulating the tilt of the camera while looking at a simple 3D cube drawn around the origin. I'm using the gluLookAt() function from Cocos2d which is supposed to emulate the OpenGL version and it seems that when I try to tinker with any of the values, my cube disappears.
My question is: Can you provide a gluLookAt() usage here that will get me started manipulating the camera so I can figure out how this works? I'm really just interesting in learning how to tilt the camera along the Y axis.
Here is my current code:
Viewport Configuration
glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
glViewport(0, 0, _backingWidth, _backingHeight);
Projection Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Maybe this should be a perspective projection?? If so,
// can you provide an example using gluPerspective()?
glOrthof(-_backingWidth, _backingWidth,-_backingHeight, _backingHeight, -1, 1);
ModelView Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt() // What goes here?
Drawing Code
static const GLfloat cubeVertices[] = {
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
};
static const GLushort cubeIndices[] = {
0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
};
static const GLubyte cubeColors[] = {
255, 255, 0, 255,
0, 255, 255, 255,
0, 0, 0, 0,
255, 0, 255, 255,
255, 255, 0, 255,
0, 255, 255, 255,
0, 0, 0, 0,
255, 0, 255, 255
};
glVertexPointer(3, GL_FLOAT, 0, cubeVertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cubeColors);
glEnableClientState(GL_COLOR_ARRAY);
glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, cubeIndices);
I'm not completely sure what exactly you want, but here some explanations:
gluLookAt expects 3 vectors (each as 3 doubles): first the position of the camera (eye point), then the position to where you look (center point) and finally an up-vector that specifies an up-direction (this need not be the perfect orthogonal upward direction, as it is reorthogonalized anyway).
So if you stand at (0,0,5) and look at your cube (that is at the center) and want the y-axis to be the up-direction, you would call gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) to see your cube in full beauty.
If you want to tilt your head to the side, you just need to change the up-vector and rotate it to the side a bit. Or if you want to look up, but without tilting the head to the side, you still use the y-axis as up-vector, but you just look at another point, so you change the center point to a point above and in front of you (maybe rotated about the eye position). But this won't work if you want to look straight up, in this case you need to change the up-vector to something orthogonal to the y-axis (in addition to setting the center point to a point straight above you, of course).
But I think you want a perspective projection. Your current ortho is at least quite inappropriate for your coordinates, as it specifies a coordinate system in which coordinates are in the size of pixel, so your [-1,1]-cube is about the size of a pixel on the screen. Try gluPerspective(60.0, ((double)_backingWidth)/_backingHeight, 0.1, 100.0). If you really want an orthographic projection without any realistic perspective distortion, you can use glOrtho, but in this case you should keep the size proprtions of the glOrtho parameters and your model's coordinates roughly in-sync (therefore not specify a screen-sized ortho and using coordinates in the [-1,1] range).
Why does this only draw black?
glPushMatrix();
// Check the current color
glColor3i(255, 0, 255);
GLint currentColor[4];
glGetIntegerv(GL_CURRENT_COLOR, currentColor);
//currentColor[0] = 254, 1 = 0, 2 = 254, 3 = doesn't matter
glBegin(GL_QUADS);
glLineWidth(1);
glVertex2f(0, 0);
glVertex2f(WINDOW_WIDTH * .1, 0);
glVertex2f(WINDOW_WIDTH * .1, WINDOW_HEIGHT);
glVertex2f(0, WINDOW_HEIGHT);
glEnd();
glPopMatrix();
From memory, I think that glColor3i uses colour values that are scaled to cover the full integer range. Hence your 255 values are approximately equal to zero.....
Try 2147483647 instead.
All typed integral gl entrypoints have this range behavior. Floating point variants use normalized values: 0.0 - 1.0. glColor sets the current vertex color which even affects the output during vertex array processing if glColorPointer is not enabled (if indeed your version of GL uses named vertex attributes and not generic as in OpenGLES 2.x and greater).
Common variants for glColor are glColor{3,4}{u,b} and glColor{3,4}f.
In your case you should stick to your 0xFF values and use glColor3ub(255, 0, 255) or perhaps easier glColor3f(1.0f, 0.0f, 1.0f).
Using an integral value of INT_MAX or ~2 billion in conjunction with glColor3i() doesn't read very well.
I'm doing my first steps with OpenGL ES 2.0 trying things on my ipod touch. I was wondering how to solve this coordinates issue..
To explain better, I was trying to draw a quad and rotate/translate it using a vertex shader (also because from what I've read it seems the only way to do it).
Since I'm working with a ipod I have a 1.5 : 1 ratio and a viewport set by
glViewport(0, 0, backingWidth, backingHeight);
So 0,0 is the center and bounds for clipping should be at -1.0, -1.0, -1.0, 1.0, etc (right?)
To draw a square I had to use different values for x and y coordinates because of the aspect ratio:
static const GLfloat lineV[] = {
-0.5f, 0.33f, 0.5f, 0.33f,
0.5f, 0.33f, 0.5f,-0.33f,
0.5f,-0.33f, -0.5f,-0.33f,
-0.5f,-0.33f, -0.5f, 0.33f,
-0.5f, 0.33f, 0.5f,-0.33f,
0.5f, 0.33f, -0.5f,-0.33f,
};
It's a square with both diagonals (I know that using indexes would be more efficient but that's not the point)..
Then I tried writing a vertex shader to rotate the object while moving it:
void main()
{
m = mat4( cos(rotation), sin(rotation), 0.0, 0.0,
-sin(rotation), cos(rotation), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
m2 = mat4(1.0);
m2[1][3] = sin(rotation)*0.8;
gl_Position = position*(m*m2);
}
It works but since coordinates are not the same the quad is distorted while it rotates. How should I prevent that? I thought if it was possible to change the view frustum to have different bounds (not -1.0 to 1.0 on both axis so that enlarging on y-axis would fix the problem).
In addition is there a better way to use matrixes? I mean, I was used to use glRotatef without having to specify the whole matrix.. does convenience functions/constructors exist to accomplish this task?
The first arguments to glViewport() is not the center, it's the bottom left corner's coordinates.
You should probably set up a projection that takes your aspect into account, typically using gluPerspective() (if GLU is available in ES).
No glut or support functions are provided from what I've seen. Basically I solved it by using equal coordinates when building vertices and using a vertex shader to scale on y axis by the right aspect ratio.