How use option Kd Ks Ka [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
how use/draw "Kd Ka Ks"?
I am interested in how to use these options.
Ks[3]
Kd[3]
Ka[3]
glcolor3f(..., ..., ...);
Thanks.

These are coefficients of reflection. Ka is for ambient component, Kd is for diffuse component, and Ks is for specular component.
The Ks, Kd, and Ka are arrays of 3 elements (you can also have a 4th value, the alpha component). The elements represent the RGB colors. You can tweak these values if you want to modify how light reflects off of your surface (increase Ks for more specular lighting and making your surface more shiny, Kd for more diffuse reflection, and Ka for more ambient light, which will make everything brighter).
For example, you can modify materials using glMaterialfv:
GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat shinyness[] = { 5.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, shinyness);

S, D, and A should stand for specular, diffuse, and ambient lighting. Without surrounding code though I'm not too sure what the vectors represent. I would guess though that that is the color of the specular, ambient, and diffuse lights to be applied to the surface. There are many shading models you can check out to implement lighting, have a look at Phong: http://www.arcsynthesis.org/gltut/Illumination/Tut11%20Phong%20Model.html, http://en.wikipedia.org/wiki/Phong_shading

Related

OpenGL doesn't consider distance of GL_DIFFUSE positional light

I want to put a positional light in my scene. I expect distant objects to take less light, but opengl just care about angle between surface normal and light. Am I doing something wrong or do I have to add another function?
GLfloat lightIntensity=1.0;
GLfloat main_position[] = {0.0, 0.0, 1.0, 1.0};
GLfloat light_ambient[] = {0.2, 0.2, 0.2, 0.0};
GLfloat light_diffuse[] = {lightIntensity, lightIntensity, lightIntensity, 1.0};
GLfloat light_specular[] = {0.0, 0.0, 0.0, 0.0};
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_POSITION, main_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
When I run the code, 2 object with same surface normal have same lighting even though they have different distance from the light source
For a distance dependent light you've to set the attenuation parameters GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION respectively GL_QUADRATIC_ATTENUATION. See glLight. By default the light is constant independent on the distance.
The light attenuation is specified in OpenGL 2.0 Specification - 2.14.1 Lighting, page 62.
The light attenuation factor is defiend as:
att = 1 / (kc + kl * d + kq * d * d)
d ... distance from the light source to the fragment
kc ... constant attenuation
kl ... linear attenuation
kq ... quadratic attenuation
The default value for the constant attenuation is 1, for the linear and quadratic attenuation it is 0. This leads to a distance independent factor of 1.
e.g. In the following a attenuation is set, where the attenuation factor is <= 1.0/255.0 at a distance of max_dist:
float max_dist = ...;
float threshold = 1.0f/255.0f;
float kc = 0.0f;
float kq = 0.0f;
float kl = (1.0f/threshold - kc - kq*max_dist*max_dist) / max_dist;
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, kc);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, kl);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, kq);
For quadratic attenuation the same can be achieved by
float kc = 0.0f;
float kl = 0.0f;
float kq = (1.0f/threshold - kc - kl*max_dist) / (max_dist*max_dist);

Why is this triangle strip only painting a third of the screen? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying to make a toy to "paint" fragment shaders on the whole screen. To that end I am attempting to "fill" the screen with a single triangle strip. I am using QT for this since I have a UI I want to use besides the openGL rendering.
I am basing the full screen triangle strip technique off:
https://github.com/Gargaj/Bonzomatic/blob/master/src/platform_glfw/Renderer.cpp
static const char *fragmentShaderSource =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = vec4(1.0,0.0,0.0,0.0);\n"
"}\n";
static float pFullscreenQuadVertices[] =
{
-1.0, -1.0, 0.5, 0.0, 0.0,
-1.0, 1.0, 0.5, 0.0, 1.0,
1.0, -1.0, 0.5, 1.0, 0.0,
1.0, 1.0, 0.5, 1.0, 1.0,
};
static const char *szVertexShader =
"#version 410 core\n"
"in vec3 in_pos;\n"
"in vec2 in_texcoord;\n"
"out vec2 out_texcoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4( in_pos.x, in_pos.y, in_pos.z, 1.0 );\n"
" out_texcoord = in_texcoord;\n"
"}";
void DemoRender::initializeGL(){
m_background = qRgb(255,255,255);
initializeOpenGLFunctions();
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, szVertexShader);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_program->log();
m_posAttr = m_program->attributeLocation("in_pos");
m_vao1.create();
m_vao1.bind();
}
void DemoRender::paintGL(){
QPainter painter;
painter.begin(this);
painter.beginNativePainting();
glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(),0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glFrontFace(GL_CW);
//glCullFace(GL_FRONT);
//glEnable(GL_CULL_FACE);
//glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
drawFullScreen();
m_program->release();
//glDisable(GL_DEPTH_TEST);
//glDisable(GL_CULL_FACE);
painter.endNativePainting();
painter.end();
update();
}
void DemoRender::drawFullScreen(){
m_vao1.bind();
m_vbo1.create();
m_vbo1.bind();
m_vbo1.allocate(pFullscreenQuadVertices,sizeof(pFullscreenQuadVertices)*sizeof(float));
m_vbo1.write(0,pFullscreenQuadVertices,sizeof(pFullscreenQuadVertices));
m_program->enableAttributeArray(m_posAttr);
//m_vbo1.release();
//I suspect you are the culprit, but I don't know how to fix it.
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3);
m_vbo1.release();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_program->disableAttributeArray(m_posAttr);
}
as a debug technique I am telling the fragment shader to make every pixel red. Now, my confusion is this: Why is only about a third of the screen turning red?
It appears the vertex shader isn't covering the entire screen space. What can I do to fix this?
My current theory is that the triangle strip isn't rendering right due to some detail of how the vertex array is set up, but because qt wont let me do this C-style I can't follow the original author's code one for one.
The vertex attribute pointer, specifically the stride, is wrong. The data contains a 3-component position and two additional floats, but the default stride assumes tight packing. The correct code should be:
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3, 5*sizeof(float))
Where 5 * sizeof(float) is the by offset between the start of a vertex and the start of the next vertex.

Rotating a light around a stationary object in openGL/glsl

So, I'm trying to rotate a light around a stationary object in the center of my scene. I'm well aware that I will need to use the rotation matrix in order to make this transformation occur. However, I'm unsure of how to do it in code. I'm new to linear algebra, so any help with explanations along the way would help a lot.
Basically, I'm working with these two right now and I'm not sure of how to make the light circulate the object.
mat4 rotation = mat4(
vec4( cos(aTimer), 0.0, sin(aTimer), 0.0),
vec4( 0, 1.0, 0.0, 0.0),
vec4(-sin(aTimer), 0.0, cos(aTimer), 0.0),
vec4( 0.0, 0.0, 0.0, 1.0)
);
and this is how my light is set up :
float lightPosition[4] = {5.0, 5.0, 1.0, 0};
glLightfv(GL_LIGHT0, GL_POSITION, lightPositon);
The aTimer in this code is a constantly incrementing float.
Even though you want the light to rotate around your object, you must not use a rotation matrix for this purpose but a translation one.
The matrix you're handling is the model matrix. It defines the orientation, the position and the scale of your object.
The matrix you have here is a rotation matrix, so the orientation of the light will change, but not the position, which is what you want.
So there is two problems to fix here :
1.Define your matrix properly. Since you want a translation (circular), I think this is the matrix you need :
mat4 rotation = mat4(
vec4( 1.0, 0.0, 0.0, 0.0),
vec4( 0.0, 1.0, 0.0, 0.0),
vec4( 0.0, 0.0, 1.0, 0.0),
vec4( cos(aTimer), sin(aTimer), 0.0, 1.0)
);
2.Define a good position vertex for your light. Since it's a single vertex and it's the job of the model matrix (above) to move the light, the light vector 4D should be :
float lightPosition[4] = {0.0f, 0.0f, 0.0f, 1.0f};
//In C, 0.0 is a double, you may have warnings at compilation for loss of precision, so use the suffix "f"
The forth component must be one since it's thanks to it that translations are possible.
You may find additional information here
Model matrix in 3D graphics / OpenGL
However they are using column vectors. Judging from your rotation matrix I do belive you use row vectors, so the translation components are in the last row, not the last column of the model matrix.

Bad shading result when applying material

I've got an openGL 3d scene with two simple objects (glutSolidCube and glutSolidTeapot). When I set up the lights with GL_COLOR_MATERIAL enabled, I get the following result:
Which is good. Then when I set up my own material like this:
//diffuse light color variables
GLfloat dlr = 0.4;
GLfloat dlg = 0.6;
GLfloat dlb = 0.9;
//ambient light color variables
GLfloat alr = 0.7;
GLfloat alg = 0.7;
GLfloat alb = 0.7;
//ambient light color variables
GLfloat slr = 0.4;
GLfloat slg = 0.4;
GLfloat slb = 0.4;
GLfloat DiffuseLight[] = {dlr, dlg, dlb}; //set DiffuseLight[] to the specified values
GLfloat AmbientLight[] = {alr, alg, alb}; //set AmbientLight[] to the specified values
GLfloat SpecularLight[] = {slr, slg, slb}; //set AmbientLight[] to the specified values
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&AmbientLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&DiffuseLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&SpecularLight);
I get this very different result, in which you can see it's not being shaded properly, it's like FLAT shading although I defined it as SMOOTH (Gouraud).
Where can the problem be? Is it on the material definition?
You forgot to set specular shininess.
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 12.0f);
Set it to 10...25 and it'll look much better/shinier. It won't look as good as per-pixel lighting, though. Default value for shininess is zero which will look exactly like what you see - i.e. ugly.
I get this very different result, in which you can see it's not being shaded properly, it's like FLAT shading although I defined it as SMOOTH (Gouraud).
Well, you got smooth shading. However the OpenGL fixed function pipeline evaluates illumination values only at the vertices, then performs barycentric interpolation over the face. The result you got is exactly what to expect.
What you want is per pixel/fragment illumination. Only way to get this is by using a shader (well, it's also possible by tinkering with the so called "texture combiner environment", but getting that one to work properly is a lot of hard work. Implementing a Phong illumination shader is a matter of minutes).
By changing your lighting and material settings you're just putting emphasis on the shortcommings of the Gouraud shading model.

OpenGL lighting small objects?

I'm having a problem with lighting when dealing with really small particles. I'm doing particle-based fluid simulation and am right now rendering the fluid as really tiny polygonized spheres (by really tiny I'm saying about 0.03 units radius for the spheres). The lighting in my scene isn't lighting them how I want and I can't get it to look right. I'm looking for something similar to the soft lighting on the particles in this image...
However my particles look like this...
See how my particles have bright white sections whereas the green particles are just lit up softly and don't have large white hotspots. I know the reason is either the settings for my light or simply the fact that the particles are so small that the light takes up a larger space (is that possible??). My settings for lighting are as follows...
GLfloat mat_ambient[] = {0.5, 0.5, 0.5, 1.0};
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {10.0};
GLfloat light_position[] = {0.0, 0.1, p_z, 1.0};
GLfloat model_ambient[] = {0.5, 0.5, 0.5, 1.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
Thanks for all the suggestions everyone but unfortunately nothing worked. I sat down with my graphics professor and we determined that this problem was in fact related to the size of the particles and the fact that OpenGL treats directional lights as being infinitely far away from any vertex. The proper way to fix it was modifying the constant attenuation of the light source like this...
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 10.0);
Now my particles look like this...
which is exactly the lighting I was after!
The size of the particles isn't an issue - you're over-saturating your colours.
For each RGB component, you should have ambient + diffuse + specular <= 1.0
For a scene like this I'd expect ambient to be no more than 0.1 or so, diffuse of 0.6 or so, and specular making up the rest.
It looks like you need to turn down the specular component of your material, turn down the ambient a bit, and add some diffuse shading (GL_DIFFUSE). Consider also positioning the light behind the the viewport/camera.