How do I draw a rotating prism in OpenGL? - delphi

I'm trying to draw a simple crystal that rotates on its axis. I can get the shape right easily enough by drawing a pyramid and then drawing it again upside down, but I've got two problems.
First off, even though I draw everything in the same color, two of the faces come out a different color as the other two.
Second, it's placing a "bottom" on each pyramid that's visible through the translucent walls of the crystal, which ruins the effect. Is there any way to get rid of it?
Here's the code I'm using to set up and draw the GL scene. There's a lot more OpenGL code than this, of course, but this is the relevant part.
procedure Initialize;
begin
glShadeModel(GL_SMOOTH);
glClearColor(0.0, 0.0, 0.0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
end;
procedure Draw; //gets called in a loop
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5,-0.5,-6.0);
glRotatef(rotation,0.0,1.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glColor4f(0, 0, 1, 0.2);
glVertex3f(0, 3.4, 0);
glVertex3f(-1, 0, -1);
glVertex3f(-1, 0, 1);
glVertex3f(1, 0, 1);
glVertex3f(1, 0, -1);
glVertex3f(-1, 0, -1);
glEnd;
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, -3.4, 0);
glVertex3f(-1, 0, -1);
glVertex3f(-1, 0, 1);
glVertex3f(1, 0, 1);
glVertex3f(1, 0, -1);
glVertex3f(-1, 0, -1);
glEnd;
rotation := rotation + 0.02;
end;
Anyone know what I'm doing wrong and how to fix it?

I'm trying to draw a simple crystal
Stop. Crystals are translucent, and the moment you start drawing translucent objects, you can basically discard any notion of the effect being "simple". Rendering a true prism (which refracts different wavelengths of light differently) is something that requires raytracing of some form to get right. And there are many ray tracers that can't even get it right, since they only trace R, G and B wavelengths, whereas you need to trace many wavelengths to approximate the refraction and light splitting pattern of a prism.
The best you're going to get is on a rasterizer like OpenGL some level of fakery.
I can't explain what's going on with the faces, but the problem with seeing through to the other polygons is simple: you're not using backface culling. Unless you want to see the back faces of transparent objects, you need to make sure that backface culling is active.

Related

Why does the whole world translate instead of just the object?

I have not been able to translate my object alone, when I try to do that, the whole world would translate instead.
Anyone have any ideas why this is happening?
d3ddev->SetStreamSource(0, v_buffer[2], 0, sizeof(CUSTOMVERTEX));
d3ddev->SetIndices(i_buffer[2]);
d3ddev->SetTexture(0, texture[1]);
D3DXMATRIX matTranslate;
D3DXMatrixTranslation(&matTranslate, 30.0f, 0.0f, 30.0f);
d3ddev->SetTransform(D3DTS_WORLD, &matTranslate);
d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
The D3D device acts as a state machine. Whenever you set some state on the device, like the world transform matrix, it will persist between multiple draw calls. After you draw your object, you must reset the world transform back to the identity matrix before drawing the rest of the scene to prevent it from being translated.
D3DXMATRIX matIdentity;
D3DXMatrixIdentity(&matIdentity);
d3ddev->SetTransform(D3DTS_WORLD, &matIdentity);

Antialised Circle with texture mapping

i have a question about a circle which has a texture mapping. My code works well but i have not antialised edges so it is not smooth and looks not good. I have read now about 3 hours and found some solutions but i don't know how can i implement them in my code. There were two solutions which sounds pretty good.
First was a blurry texture which should bind instead of a non blurry to have smooth edges.
Second add color vertices on the edges with opacity to have smooth edges. My currently draw function looks like this:
CC_NODE_DRAW_SETUP();
[self.shaderProgram use];
ccGLBindTexture2D( _texture.name );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ccGLBlendFunc( _blendFunc.src, _blendFunc.dst);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
// Send the texture coordinates to OpenGL
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, _textCoords);
// Send the polygon coordinates to OpenGL
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, _triangleFanPos);
// Draw it
glDrawArrays(GL_TRIANGLE_FAN, 0, _numOfSegements+2);
I am currently using cococs2d version 3. I asked a similar question and found only the solution of enable the multisampling on cocos2d but this break my fps to 30.
So maybe there is someone how can help me.

iOS OpenGL drawing lines : Not anti-aliasing

I'm trying to render a waveform in an EAGLContext View, and I can't for the life of me get it to anti-alias. Is anything clearly wrong with my OpenGL Code? Is anymore information required?
glLineWidth( 0.4f);// - pass * 1.0f);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glColor4f(1., 1., 1., 1.);
// Set up vertex pointer,
glVertexPointer(2, GL_FLOAT, 0, oscilLine);
// and draw the line.
glDrawArrays(GL_LINE_STRIP, 0, kDefaultDrawSamples);
Is anything clearly wrong with my OpenGL Code?
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
^^^^^^^^^^^^^^^^^^^^
Try changing this to GL_LINE_SMOOTH_HINT?
Also, since you're using the deprecated 1.x APIs you should use glGet with GL_LINE_WIDTH_RANGE and GL_LINE_WIDTH_GRANULARITY to verify that the 0.4 value is actually a supported width. You also need to ensure that the rendering target you've created has bits for an alpha channel. Can you add the context creation code?
Finally, it's not quite canon, but according to this article this mechanism of line smoothing doesn't work on iOS devices, though it apparently may on the simulator.

glDrawArrays from iOS to OSX

I'm trying to get a game I made for iOS work in OSX. And so far I have been able to get everything working except for the drawing of some random generated hills using a glbound texture.
It works perfectly in iOS but somehow this part is the only thing not visible when the app is run in OSX. I checked all coords and color values so I'm pretty sure it has to do with OpenGL somehow.
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindTexture(GL_TEXTURE_2D, _textureSprite.texture.name);
glColor4f(_terrainColor.r,_terrainColor.g,_terrainColor.b, 1);
glVertexPointer(2, GL_FLOAT, 0, _hillVertices);
glTexCoordPointer(2, GL_FLOAT, 0, _hillTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)_nHillVertices);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
You're disabling the texture coordinate (and color) array along with the texturing unit, yet are binding a texture coordinate pointer.
Is this really what you intend to do?
Appearantly it was being drawn after all, only as a 1/2 pixel line. Somehow there is some scaling on the vertices in effect, will have to check my code.

iOS - zoom only part of display using openGL ES

I'm working on a level builder app to build content for a game. Part of the iPad screen is a dedicated control panel, while the rest is a graphical representation of the level being built. I need to zoom the level area in and out without affecting the control panel. I'm using openGL ES for rendering. Can anyone give me some pointers here? Can I split the screen with different viewports and so just scale one?
The trick is to understand that OpenGL is a state machine and there is no such thing like "global initialization". As long as you follow the badly written tutorials and have your projection matrix setup in the window resize handler you'll be stuck. What you actually do is something like this:
void render_perspective_scene(void);
void render_ortho_scene(void);
void render_HUD();
void display()
{
float const aspect = (float)win_width/(float)win_height;
glViewport(0,0,win_width,win_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-aspect*near/lens, aspect*near/lens, -near/lens, near/lens, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_perspective_scene();
glEnable(GL_SCISSOR_TEST);
// just clear the depth buffer, so that everything that's
// drawn next will overlay the previously rendered scene.
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(ortho_x, ortho_y, ortho_width, ortho_height);
glScissor(ortho_x, ortho_y, ortho_width, ortho_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect*scale, aspect*scale, -scale, scale, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_ortho_scene();
// Same for the HUD, only that we render
// that one in pixel coordinates.
glViewport(hud_x, hud_y, hud_width, hud_height);
glScissor(hud_x, hud_y, hud_width, hud_height);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, win_width, 0, win_height, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_HUD();
}
The important part is, that you set the viewport/scissor and the projection within the drawing handler prior to rendering that sub-part.
If you're rendering with OpenGL ES (presumably 2.0), then you have full control over the scaling of what you render. You decide where the scale gets applied, and you decide how things are rendered.
I'd guess your code currently looks a bit like this.
Get view scale
Apply view scale to view matrix
Render level
Render control panel
When it should look like this.
Render control panel
Get view scale
Apply view scale to view matrix
Render level
The matrices (or whatever transformation stuff you have) you use for transforming the level should not be used for transforming the control panel.

Resources