Can you please submit a code for drawing a basic wireframe sphere without texturing it. I found plenty of examples but they use 3 kind of buffers like normal,texture and vertices. Is there any simple comprehensive way to draw a sphere using GL_TRIANGLE_FAN or GL_TRIANGLE_STRIP and using only vertex and fragment shader.
Thank you!
void DrawSphere(GLdouble radius, int longitudeSubdiv, int latitudeSubdiv)
{
// issue corresponding GL command
//glPolygonMode(GL_BACK,GL_FILL);
//gluSphere(m_quadrObj,radius,longitudeSubdiv,latitudeSubdiv);
float color1[3] = {1.0,0.0,0.0};
float shininess = 64.0f;
float specularColor[] = {1.0, 1.0f, 1.0f, 1.0f};
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); // range 0 ~ 128
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
glPushMatrix();
glTranslatef(1,1,1);// *
glColor3fv(color1);
gluSphere(m_quadrObj,radius,longitudeSubdiv,latitudeSubdiv);
glPopMatrix();
//glColor3fv(color2);
}
Related
I was trying to implement the terrain tutorial in Introduction to game programming by frank luna. I succeeded to implement it using the effect file.
When I try to separate the Vertex, hull, domain and pixel shaders, I got a very strange behavior in the terrain textures. After debugging I got that the problem is in calculating the UV texture coordinates in the domain shader.
Here is how I calculate the UV coordinates.
[domain("quad")]
DomainOut main(PatchTess patchTess,
float2 uv : SV_DomainLocation,
const OutputPatch<HullOut, 4> quad)
{
DomainOut dout;
// Bilinear interpolation.
dout.PosW = lerp(
lerp(quad[0].PosW, quad[1].PosW, uv.x),
lerp(quad[2].PosW, quad[3].PosW, uv.x),
uv.y);
dout.Tex = lerp(
lerp(quad[0].Tex, quad[1].Tex, uv.x),
lerp(quad[2].Tex, quad[3].Tex, uv.x),
uv.y);
// Tile layer textures over terrain.
dout.TiledTex = dout.Tex * 50.0f;
dout.TiledTex = dout.Tex*50.0f;
// Displacement mapping
dout.PosW.y = gHeightMap.SampleLevel(samHeightmap, dout.Tex, 0).r;
// NOTE: We tried computing the normal in the shader using finite difference,
// but the vertices move continuously with fractional_even which creates
// noticable light shimmering artifacts as the normal changes. Therefore,
// we moved the calculation to the pixel shader.
// Project to homogeneous clip space.
dout.PosH = mul(float4(dout.PosW, 1.0f), gViewProj);
return dout;
}
I am using quads for the domain shader.
After debugging using graphics analyzer, I got that in the domain shader the data is different from effect file from the domain shader I implemented altough the same code is used in both files.
What can be the problem?
I have an update to share with you, The data stream that enters to the domain shader is different from the effect file from the separated files. It is not the equation for the calculation.
What makes the data stream different, is there any way to change the order of patches enters the domain shader from the Hull shader.
This is the pixel shader code:
Texture2DArray gLayerMapArray : register(t3);
Texture2D gBlendMap : register(t1);
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
struct DomainOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float2 Tex : TEXCOORD0;
float2 TiledTex : TEXCOORD1;
};
float4 main(DomainOut pin) : SV_Target
{
//
// Texturing
//
float4 c0 = gLayerMapArray.Sample(samLinear, float3(pin.TiledTex, 0.0f));
float4 c1 = gLayerMapArray.Sample(samLinear, float3(pin.TiledTex, 1.0f));
float4 c2 = gLayerMapArray.Sample(samLinear, float3(pin.TiledTex, 2.0f));
float4 c3 = gLayerMapArray.Sample(samLinear, float3(pin.TiledTex, 3.0f));
// Sample the blend map.
float4 t = gBlendMap.Sample(samLinear, pin.Tex);
// Blend the layers on top of each other.
float4 texColor = c0;
texColor = lerp(texColor, c1, t.r);
texColor = lerp(texColor, c2, t.g);
texColor = lerp(texColor, c3, t.b);
return texColor;
}
Finally, the solution is that I should set the sampler from c++ code even if you have a sampler in the shader. I don't know why but this solved the problem.
I have a 360 texture in Equirectangular Projection.
With what GLSL shader can I convert it into a azimuthal equidistant projection?
See also:
http://earth.nullschool.net/#current/wind/isobaric/500hPa/azimuthal_equidistant=24.64,98.15,169
I would do it in Fragment shader.
bind Equirectangular texture as 2D texture
bind projection shader
draw Quad covering the screen or target texture
store or use the result.
In Vertex shader I would:
Just pass the vertex coordinates as varying to fragment shader (no point using matrices here you can directly use x,y coordinates in range <-1,+1>)
In fragment shader I would:
compute azimuth and distance of interpolated vertex from point (0,0) (simple length and atan2 call)
then convert them to (u,v) coordinates of texture (just scale...)
and lastly render fragment with selected texel or throw it out if out of range ...
[edit1] just did bust a small example:
GL draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr"); glUniform1i(id,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,txrmap);
glBegin(GL_QUADS);
glColor3f(1,1,1);
glVertex2f(-1.0,-1.0);
glVertex2f(-1.0,+1.0);
glVertex2f(+1.0,+1.0);
glVertex2f(+1.0,-1.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
glUseProgram(0);
glFlush();
SwapBuffers(hdc);
Vertex:
varying vec2 pos;
void main()
{
pos=gl_Vertex.xy;
gl_Position=gl_Vertex;
}
Fragment:
uniform sampler2D txr;
varying vec2 pos;
void main()
{
const float pi2=6.283185307179586476925286766559;
vec4 c=vec4(0.0,0.0,0.0,1.0);
vec2 uv; // texture coord = scaled spherical coordinates
float a,d; // azimuth,distance
d=length(pos);
if (d<1.0) // inside projected sphere surface
{
a=atan(-pos.x,pos.y);
if (a<0.0) a+=pi2;
if (a>pi2) a-=pi2;
uv.x=a/pi2;
uv.y=d;
c=texture2D(txr,uv);
}
gl_FragColor=c;
}
Input texture:
Output render:
[notes]
The vertical line is caused by not using GL_CLAMP_TO_EDGE on source texture. It can be repaired by using texture coordinates range shifted by 1 pixel on booth sides or use GL_CLAMP_TO_EDGE extension if present.
Weird atan() operands are result of rotating left by 90 degrees to match North azimuth to be UP.
I use the following fragment shader, which uses the fog effect, to draw my scene:
precision mediump float;
uniform int EnableFog;
uniform float FogMinDist;
uniform float FogMaxDist;
varying lowp vec4 DestinationColor;
varying float EyeToVertexDist;
float computeFogFactor()
{
float fogFactor = 1.0;
if (EnableFog != 0)
{
//Use a bit lower vlaue of FogMaxDist to get a better fog effect - it will make the far end disappear quicker.
float fogMaxDistABitCloser = FogMaxDist * 0.98;
fogFactor = (fogMaxDistABitCloser - EyeToVertexDist) / (fogMaxDistABitCloser - FogMinDist);
fogFactor = clamp(fogFactor, 0.0, 1.0);
}
return fogFactor;
}
void main(void)
{
float fogFactor = computeFogFactor();
gl_FragColor = DestinationColor * fogFactor;
}
And i enable alpha blending:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
The result is the following scene:
My problem is with the places in which the lines overlap - the result is that the color seems darker than the color of both lines:
How i can fix it?
As already described in the comment you are blending the newly drawn line with the background which may already contain colours from another object at certain pixels, in your case where lines overlap. To solve this you will either have to draw your lines without overlapping or make your drawing independent from the current buffer state.
In your specific case you may pass the background colour to your fragment shader via some uniform or even a texture and then do your blending manually in the fragment shader.
In general you might want to draw the grid to some frame buffer object (FBO) with attached texture and then draw the whole texture in a single draw call using your fog shader and blending. The drawing to FBO should then be with disabled blending.
There are other ways such as drawing the grid to a stencil buffer first and then redraw a full-screen rect applying a colour with your shader and blending.
I'm learning OpenGL 3.3, using some tutorials (http://opengl-tutorial.org). In the tutorial I'm using, there is a vertex shader which does the following:
Tutorial Shader source
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
}
Yet, when I try to emulate the same behavior in my application, I get the following:
error: implicit cast from "vec4" to "vec3".
After seeing this, I wasn't sure if it was because I was using 4.2 version shaders as opposed to 3.3, so changed everything to match what the author had been using, still receiving the same error afterward.
So, I changed my shader to do this:
My (latest) Source
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
void main()
{
vec4 a = vec4(vertexPosition_modelspace, 1);
gl_Position.xyz = MVP * a;
}
Which, of course, still produces the same error.
Does anyone know why this is the case, as well as what a solution might be to this? I'm not sure if it could be my calling code (which I've posted, just in case).
Calling Code
static const GLfloat T_VERTEX_BUF_DATA[] =
{
// x, y z
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
static const GLushort T_ELEMENT_BUF_DATA[] =
{ 0, 1, 2 };
void TriangleDemo::Run(void)
{
glClear(GL_COLOR_BUFFER_BIT);
GLuint matrixID = glGetUniformLocation(mProgramID, "MVP");
glUseProgram(mProgramID);
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mMVP[0][0]); // This sends our transformation to the MVP uniform matrix, in the currently bound vertex shader
const GLuint vertexShaderID = 0;
glEnableVertexAttribArray(vertexShaderID);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glVertexAttribPointer(
vertexShaderID, // Specify the ID of the shader to point to (in this case, the shader is built in to GL, which will just produce a white triangle)
3, // Specify the number of indices per vertex in the vertex buffer
GL_FLOAT, // Type of value the vertex buffer is holding as data
GL_FALSE, // Normalized?
0, // Amount of stride
(void*)0 ); // Offset within the array buffer
glDrawArrays(GL_TRIANGLES, 0, 3); //0 => start index of the buffer, 3 => number of vertices
glDisableVertexAttribArray(vertexShaderID);
}
void TriangleDemo::Initialize(void)
{
glGenVertexArrays(1, &mVertexArrayID);
glBindVertexArray(mVertexArrayID);
glGenBuffers(1, &mVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(T_VERTEX_BUF_DATA), T_VERTEX_BUF_DATA, GL_STATIC_DRAW );
mProgramID = LoadShaders("v_Triangle", "f_Triangle");
glm::mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); // field of view, aspect ratio (4:3), 0.1 units near, to 100 units far
glm::mat4 view = glm::lookAt(
glm::vec3(4, 3, 3), // Camera is at (4, 3, 3) in world space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // this is the up vector - the head of the camera is facing upwards. We'd use (0, -1, 0) to look upside down
);
glm::mat4 model = glm::mat4(1.0f); // set model matrix to identity matrix, meaning the model will be at the origin
mMVP = projection * view * model;
}
Notes
I'm in Visual Studio 2012
I'm using Shader Maker for the GLSL editing
I can't say what's wrong with the tutorial code.
In "My latest source" though, there's
gl_Position.xyz = MVP * a;
which looks weird because you're assigning a vec4 to a vec3.
EDIT
I can't reproduce your problem.
I have used a trivial fragment shader for testing...
#version 330 core
void main()
{
}
Testing "Tutorial Shader source":
3.3.11762 Core Profile Context
Log: Vertex shader was successfully compiled to run on hardware.
Log: Fragment shader was successfully compiled to run on hardware.
Log: Vertex shader(s) linked, fragment shader(s) linked.
Testing "My latest source":
3.3.11762 Core Profile Context
Log: Vertex shader was successfully compiled to run on hardware.
WARNING: 0:11: warning(#402) Implicit truncation of vector from size 4 to size 3.
Log: Fragment shader was successfully compiled to run on hardware.
Log: Vertex shader(s) linked, fragment shader(s) linked.
And the warning goes away after replacing gl_Position.xyz with gl_Position.
What's your setup? Do you have a correct version of OpenGL context? Is glGetError() silent?
Finally, are your GPU drivers up-to-date?
I've had problems with some GPUs (ATi ones, I believe) not liking integer literals when it expects a float. Try changing
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
To
gl_Position = MVP * vec4(vertexPosition_modelspace, 1.0);
I just came across this error message on an ATI Radeon HD 7900 with latest drivers installed while compiling some sample code associated with the book "3D Engine Design for Virtual Globes" (http://www.virtualglobebook.com).
Here is the original fragment shader line:
fragmentColor = mix(vec3(0.0, intensity, 0.0), vec3(intensity, 0.0, 0.0), (distanceToContour < dF));
The solution is to cast the offending Boolean expression into float, as in:
fragmentColor = mix(vec3(0.0, intensity, 0.0), vec3(intensity, 0.0, 0.0), float(distanceToContour < dF));
The manual for mix (http://www.opengl.org/sdk/docs/manglsl) states
For the variants of mix where a is genBType, elements for which a[i] is false, the result for that
element is taken from x, and where a[i] is true, it will be taken from y.
So, since a Boolean blend value should be accepted by the compiler without comment, I think this should go down as an AMD/ATI driver issue.
I am building a robot in openGL and it should move and rotate. When I press the robot should move forward and if I press t then he should rotate 15* about its own local axis and then if i press f he will walk again. I have done, the robot walks and rotates but the problem is he is not rotating with respect to his local axis, he is following (0,0,0). I think i dont understand how the composition of translation and rotation has to be made so that I get my desired effect.
I am trying now with just a scaled sphere. I am adding the display func here, so that it is more clear for you guys:
void display()
{
glEnable(GL_DEPTH_TEST); // need depth test to correctly draw 3D objects
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
//All color and material stuffs go here
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE); // normalize normals
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
// set up the parameters for lighting
GLfloat light_ambient[] = {0,0,0,1};
GLfloat light_diffuse[] = {.6,.6,.6,1};
GLfloat light_specular[] = {1,1,1,1};
GLfloat light_pos[] = {10,10,10,1};
glLightfv(GL_LIGHT0,GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
GLfloat mat_specular[] = {.9, .9, .9,1};
GLfloat mat_shine[] = {10};
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shine);
//color specs ends ////////////////////////////////////////
//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); // comment this line to enable polygon shades
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, 1, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
gluLookAt(0,0,30,0,0,0,0,1,0);
glRotatef(x_angle, 0, 1,0); // this is just for mouse handling
glRotatef(y_angle, 1,0,0); // this is just for mouse handling
glScalef(scale_size, scale_size, scale_size); // for zooming effect
draw_coordinate();
//Drawing using VBO starts here
glTranslatef(walk*sin(M_PI*turn/180),0,walk*cos(M_PI*turn/180));
glRotatef(turn,0,1,0);
draw_sphere(3,1,1);
glDisableClientState(GL_VERTEX_ARRAY); // enable the vertex array on the client side
glDisableClientState(GL_NORMAL_ARRAY); // enable the normal array on the client side
glutSwapBuffers();
}
The rotatefunction from opengl is one that rotates around (0,0,0). You have to translate the rotationpoint to the center and then do the rotation.
...
glTranslatef(walk*sin(M_PI*turn/180),0,walk*cos(M_PI*turn/180));
glTranslatef(-x_rot,-y_rot,-z_rot);
glRotatef(turn,0,1,0);
glTranslatef(x_rot,y_rot,z_rot);
...
So In your case x_rot=walk*sin(M_PI*turn/180), y_rot=0 and z_rot=walk*cos(M_PI*turn/180). The above becomes:
...
glRotatef(turn,0,1,0);
glTranslatef(x_rot=walk*sin(M_PI*turn/180),0,walk*cos(M_PI*turn/180));
...
If your robot doesn't rotate in its own axis then translate the robot to the center, rotate it and again translate it back to the original position. Keep your translation, rotation, scaling and drawing inside
glPushMatrix();
........your rotation,translation,scalling,drawing goes here..........
glPopMatrix();
These keeps the scene same.
If you don't understand these function then look here.