OpenGL Освещение на текстурной плоскости не работает

Я хочу зажечь плоскость текстуры, но это не работа. Свет на сплошной сфере очень хорош, но текстурная плоскость не светлая.

Целое изображение

Освещение на сплошной сфере работает хорошо.

Но освещение на плоскости текстуры не работает. (GL_DECAL, GL_REPLACE; я также попробовал GL_MODULATE)

Это фрагмент моего кода рендеринга. (Весь код на GitHub)

Загрузка текстуры.

  sf::Image image;

if (!image.loadFromFile(path))
return false;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);

glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
image.getSize().x, image.getSize().y, 0,
GL_RGBA, GL_UNSIGNED_BYTE,
image.getPixelsPtr()
);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

инициализировать

  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
//glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutSetCursor(GLUT_CURSOR_NONE);
light.Init();

camera.SetPin((GLfloat)width / 2, (GLfloat)height/2);

Показать обратный звонок

  adjustPerspective();

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_LIGHTING);

glPushMatrix();
camera.SetLookAt();
light.On();

// TODO: dsiplay processing
for (auto& obj : display_objs)
{
glPushMatrix();
obj->Draw();
glPopMatrix();
}
glPopMatrix();

// print fps and swap buffers

Функция инициализации света

  glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

// Set lighting intensity and color
glLightfv(GL_LIGHT0, GL_AMBIENT, qaAmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);
glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight);
////////////////////////////////////////////////

glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0);// set cutoff angle
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dirVector0);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 10.0); // set focusing strength

Функция Light.On ()

  glPushMatrix();
glTranslatef(2.0, 10.0, 2.0);
//glRotatef(90, 1, 0, 0);
glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dirVector0);
glPopMatrix();

glPushMatrix();
glDisable(GL_LIGHTING);
glTranslatef(2.0, 0.0, 2.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glutWireCone(tan(80.0 / 180.0 * 3.14159265),10.0,20,20);
glEnable(GL_LIGHTING);
glPopMatrix();

И это функция рисования текстурной плоскости.

  float tile_x = 0.125;

glTranslatef(x, y, z);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.GetId());
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glBegin(GL_QUADS);
// Both of the following cases not work.
glNormal3f(0, -1, 0);
glNormal3f(0, 1, 0);
glTexCoord2f(0.0, 0.0); glVertex3f(0, 0, 0);
glTexCoord2f(height*tile_x, 0.0); glVertex3f(0, 0, width);
glTexCoord2f(height*tile_x, width*tile_x); glVertex3f(height, 0, width);
glTexCoord2f(0.0, width*tile_x); glVertex3f(height, 0, 0);
glEnd();

glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);

Я изменил направление вектора, изменил glTexEnvf атрибут, изменил порядок кода, но не исправил ошибку. Я думаю, что в моем коде есть фундаментальная ошибка, но я не могу ее найти. Почему это происходит, и как мне это исправить?

0

Решение

Я хочу зажечь плоскость текстуры, но это не работа. Свет на сплошной сфере очень хорош, но текстурная плоскость не светлая.

Это проблема, вызванная Gouraud Shading модель стандартной модели освещения OpenGLs. В то время как Фонг затенение в общем означает технику, которая делает расчеты света на фрагмент, в Gouraud Shading, расчеты света выполняются для каждой вершины. Рассчитанный свет интерполируется в соответствии с Барицентрическая координата фрагмента на примитиве.

Это означает, что в вашем случае свет рассчитывается по углам наземного квадрата. Этот рассчитанный таким образом свет интерполируется для всех фрагментов между ними. Ангел нормального вектора в углах к световому вектору стремится к 90 °. Из-за этого весь наземный квадроцикл выглядит почти неосвещенным.

Так как свет рассчитывается для каждой вершины, свет рассчитывается для большего количества позиций, чем 4 угла квадра, и качество увеличивается. Обратите внимание, что свет на сферах выглядит почти идеально, потому что сфера состоит из множества вершин вокруг своей формы.

Попробуйте следующий код, который разбивает квад на плитки:

int   tiles = 5;
float u_max = height*tile_x;
float v_max = width*tile_x

glBegin(GL_QUADS);
glNormal3f(0, 1, 0);

for (int x=0; x < tiles; ++x)
{
for (int y=0; y < tiles; ++y)
{
x0 = (float)x/(float)tiles;
x1 = (float)(x+1)/(float)tiles;
y0 = (float)y/(float)tiles;
y1 = (float)(y+1)/(float)tiles;

glTexCoord2f(u_max*x0, v_max*y0);  glVertex3f(height*x0, 0, widht*y0);
glTexCoord2f(u_max*x1, v_max*y0);  glVertex3f(height*x0, 0, widht*y1);
glTexCoord2f(u_max*x1, v_max*y1);  glVertex3f(height*x1, 0, widht*y1);
glTexCoord2f(u_max*x0, v_max*y1);  glVertex3f(height*x1, 0, widht*y0);
}
}
glEnd();

Конечно, вы также можете написать свой собственный шейдер и реализовать освещение для каждого фрагмента. Но устаревшая стандартная модель освещения OpenGL с фиксированной функцией не поддерживает освещение по фрагментам.

Посмотрите разницу в примере WebGL:

(function loadscene() {

var resize, gl, gouraudDraw, phongDraw, vp_size;
var bufSphere = {};

function render(delteMS){

var shading = document.getElementById( "shading" ).value;
var shininess = document.getElementById( "shininess" ).value;
var ambientCol = [0.2, 0.2, 0.2];
var diffuseCol = [0.6, 0.6, 0.6];
var specularCol = [0.8, 0.8, 0.8];

Camera.create();
Camera.vp = vp_size;

gl.enable( gl.DEPTH_TEST );
gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

gl.disable(gl.CULL_FACE);var progDraw = shading == 0 ? gouraudDraw : phongDraw;;
// set up draw shader
ShaderProgram.Use( progDraw.prog );
ShaderProgram.SetUniformM44( progDraw.prog, "u_projectionMat44", Camera.Perspective() );
ShaderProgram.SetUniformM44( progDraw.prog, "u_viewMat44", Camera.LookAt() );
ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.lightPos", [0.0, 0.0, 0.25] )
ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.ambient", ambientCol )
ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.diffuse", diffuseCol )
ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.specular", specularCol )
ShaderProgram.SetUniformF1( progDraw.prog, "u_lightSource.shininess", shininess )
var modelMat = IdentityMat44()
modelMat = RotateAxis( modelMat, -1.5, 0 );
modelMat = RotateAxis( modelMat, CalcAng( delteMS, 17.0 ), 1 );
ShaderProgram.SetUniformM44( progDraw.prog, "u_modelMat44", modelMat );

// draw scene
VertexBuffer.Draw( bufSphere );

requestAnimationFrame(render);
}

function resize() {
//vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
vp_size = [window.innerWidth, window.innerHeight]
canvas.width = vp_size[0];
canvas.height = vp_size[1];
gl.viewport( 0, 0, vp_size[0], vp_size[1] );
}

function initScene() {

canvas = document.getElementById( "canvas");
gl = canvas.getContext( "experimental-webgl" );
if ( !gl )
return null;

gouraudDraw = {}
gouraudDraw.prog = ShaderProgram.Create(
[ { source : "gouraud-shader-vs", stage : gl.VERTEX_SHADER },
{ source : "gouraud-shader-fs", stage : gl.FRAGMENT_SHADER }
],
[ "u_projectionMat44", "u_viewMat44", "u_modelMat44",
"u_lightSource.lightDir", "u_lightSource.ambient", "u_lightSource.diffuse", "u_lightSource.specular", "u_lightSource.shininess", ] );
if ( gouraudDraw.prog == 0 )
return;
gouraudDraw.inPos = gl.getAttribLocation( gouraudDraw.prog, "inPos" );
gouraudDraw.inNV  = gl.getAttribLocation( gouraudDraw.prog, "inNV" );
gouraudDraw.inCol = gl.getAttribLocation( gouraudDraw.prog, "inCol" );

phongDraw = {}
phongDraw.prog = ShaderProgram.Create(
[ { source : "phong-shader-vs", stage : gl.VERTEX_SHADER },
{ source : "phong-shader-fs", stage : gl.FRAGMENT_SHADER }
],
[ "u_projectionMat44", "u_viewMat44", "u_modelMat44",
"u_lightSource.lightDir", "u_lightSource.ambient", "u_lightSource.diffuse", "u_lightSource.specular", "u_lightSource.shininess", ] );
if ( phongDraw.prog == 0 )
return;
phongDraw.inPos = gl.getAttribLocation( phongDraw.prog, "inPos" );
phongDraw.inNV  = gl.getAttribLocation( phongDraw.prog, "inNV" );
phongDraw.inCol = gl.getAttribLocation( phongDraw.prog, "inCol" );

// create cube
var layer_size = 16, circum_size = 32;
var rad_circum = 1.0;
var rad_tube = 0.5;
var sphere_pts = [-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0];
var sphere_nv  = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
var sphere_col = [0.8, 0.6, 0.3, 0.8, 0.6, 0.3, 0.8, 0.6, 0.3, 0.8, 0.6, 0.3];
var sphere_inx = [0, 1, 2, 0, 2, 3];
bufSphere = VertexBuffer.Create(
[ { data : sphere_pts, attrSize : 3, attrLoc : gouraudDraw.inPos },
{ data : sphere_nv, attrSize : 3, attrLoc : gouraudDraw.inNV },
{ data : sphere_col, attrSize : 3, attrLoc : gouraudDraw.inCol } ],
sphere_inx );

window.onresize = resize;
resize();
requestAnimationFrame(render);
}

function Fract( val ) {
return val - Math.trunc( val );
}
function CalcAng( deltaTime, intervall ) {
return Fract( deltaTime / (1000*intervall) ) * 2.0 * Math.PI;
}
function CalcMove( deltaTime, intervall, range ) {
var pos = self.Fract( deltaTime / (1000*intervall) ) * 2.0
var pos = pos < 1.0 ? pos : (2.0-pos)
return range[0] + (range[1] - range[0]) * pos;
}
function EllipticalPosition( a, b, angRag ) {
var a_b = a * a - b * b
var ea = (a_b <= 0) ? 0 : Math.sqrt( a_b );
var eb = (a_b >= 0) ? 0 : Math.sqrt( -a_b );
return [ a * Math.sin( angRag ) - ea, b * Math.cos( angRag ) - eb, 0 ];
}

glArrayType = typeof Float32Array !="undefined" ? Float32Array : ( typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array );

function IdentityMat44() {
var m = new glArrayType(16);
m[0]  = 1; m[1]  = 0; m[2]  = 0; m[3]  = 0;
m[4]  = 0; m[5]  = 1; m[6]  = 0; m[7]  = 0;
m[8]  = 0; m[9]  = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
};

function RotateAxis(matA, angRad, axis) {
var aMap = [ [1, 2], [2, 0], [0, 1] ];
var a0 = aMap[axis][0], a1 = aMap[axis][1];
var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
var matB = new glArrayType(16);
for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
for ( var i = 0; i < 3; ++ i ) {
matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
}
return matB;
}

function Cross( a, b ) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; }
function Dot( a, b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
function Normalize( v ) {
var len = Math.sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
return [ v[0] / len, v[1] / len, v[2] / len ];
}

var Camera = {};
Camera.create = function() {
this.pos    = [0, 2, 0.0];
this.target = [0, 0, 0];
this.up     = [0, 0, 1];
this.fov_y  = 90;
this.vp     = [800, 600];
this.near   = 0.5;
this.far    = 100.0;
}
Camera.Perspective = function() {
var fn = this.far + this.near;
var f_n = this.far - this.near;
var r = this.vp[0] / this.vp[1];
var t = 1 / Math.tan( Math.PI * this.fov_y / 360 );
var m = IdentityMat44();
m[0]  = t/r; m[1]  = 0; m[2]  =  0;                              m[3]  = 0;
m[4]  = 0;   m[5]  = t; m[6]  =  0;                              m[7]  = 0;
m[8]  = 0;   m[9]  = 0; m[10] = -fn / f_n;                       m[11] = -1;
m[12] = 0;   m[13] = 0; m[14] = -2 * this.far * this.near / f_n; m[15] =  0;
return m;
}
Camera.LookAt = function() {
var mz = Normalize( [ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ] );
var mx = Normalize( Cross( this.up, mz ) );
var my = Normalize( Cross( mz, mx ) );
var tx = Dot( mx, this.pos );
var ty = Dot( my, this.pos );
var tz = Dot( [-mz[0], -mz[1], -mz[2]], this.pos );
var m = IdentityMat44();
m[0]  = mx[0]; m[1]  = my[0]; m[2]  = mz[0]; m[3]  = 0;
m[4]  = mx[1]; m[5]  = my[1]; m[6]  = mz[1]; m[7]  = 0;
m[8]  = mx[2]; m[9]  = my[2]; m[10] = mz[2]; m[11] = 0;
m[12] = tx;    m[13] = ty;    m[14] = tz;    m[15] = 1;
return m;
}

var ShaderProgram = {};
ShaderProgram.Create = function( shaderList ) {
var shaderObjs = [];
for ( var i_sh = 0; i_sh < shaderList.length; ++ i_sh ) {
var shderObj = this.CompileShader( shaderList[i_sh].source, shaderList[i_sh].stage );
if ( shderObj == 0 )
return 0;
shaderObjs.push( shderObj );
}
var progObj = this.LinkProgram( shaderObjs )
if ( progObj != 0 ) {
progObj.attribIndex = {};
var noOfAttributes = gl.getProgramParameter( progObj, gl.ACTIVE_ATTRIBUTES );
for ( var i_n = 0; i_n < noOfAttributes; ++ i_n ) {
var name = gl.getActiveAttrib( progObj, i_n ).name;
progObj.attribIndex[name] = gl.getAttribLocation( progObj, name );
}
progObj.unifomLocation = {};
var noOfUniforms = gl.getProgramParameter( progObj, gl.ACTIVE_UNIFORMS );
for ( var i_n = 0; i_n < noOfUniforms; ++ i_n ) {
var name = gl.getActiveUniform( progObj, i_n ).name;
progObj.unifomLocation[name] = gl.getUniformLocation( progObj, name );
}
}
return progObj;
}
ShaderProgram.AttributeIndex = function( progObj, name ) { return progObj.attribIndex[name]; }
ShaderProgram.UniformLocation = function( progObj, name ) { return progObj.unifomLocation[name]; }
ShaderProgram.Use = function( progObj ) { gl.useProgram( progObj ); }
ShaderProgram.SetUniformI1  = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1i( progObj.unifomLocation[name], val ); }
ShaderProgram.SetUniformF1  = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1f( progObj.unifomLocation[name], val ); }
ShaderProgram.SetUniformF2  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform2fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformF3  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform3fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformF4  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform4fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformM33 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix3fv( progObj.unifomLocation[name], false, mat ); }
ShaderProgram.SetUniformM44 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix4fv( progObj.unifomLocation[name], false, mat ); }
ShaderProgram.CompileShader = function( source, shaderStage ) {
var shaderScript = document.getElementById(source);
if (shaderScript)
source = shaderScript.text;
var shaderObj = gl.createShader( shaderStage );
gl.shaderSource( shaderObj, source );
gl.compileShader( shaderObj );
var status = gl.getShaderParameter( shaderObj, gl.COMPILE_STATUS );
if ( !status ) alert(gl.getShaderInfoLog(shaderObj));
return status ? shaderObj : null;
}
ShaderProgram.LinkProgram = function( shaderObjs ) {
var prog = gl.createProgram();
for ( var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh )
gl.attachShader( prog, shaderObjs[i_sh] );
gl.linkProgram( prog );
status = gl.getProgramParameter( prog, gl.LINK_STATUS );
if ( !status ) alert("Could not initialise shaders");
gl.useProgram( null );
return status ? prog : null;
}

var VertexBuffer = {};
VertexBuffer.Create = function( attributes, indices ) {
var buffer = {};
buffer.buf = [];
buffer.attr = []
for ( var i = 0; i < attributes.length; ++ i ) {
buffer.buf.push( gl.createBuffer() );
buffer.attr.push( { size : attributes[i].attrSize, loc : attributes[i].attrLoc } );
gl.bindBuffer( gl.ARRAY_BUFFER, buffer.buf[i] );
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( attributes[i].data ), gl.STATIC_DRAW );
}
buffer.inx = gl.createBuffer();
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, buffer.inx );
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW );
buffer.inxLen = indices.length;
gl.bindBuffer( gl.ARRAY_BUFFER, null );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
return buffer;
}
VertexBuffer.Draw = function( bufObj ) {
for ( var i = 0; i < bufObj.buf.length; ++ i ) {
gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.buf[i] );
gl.vertexAttribPointer( bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( bufObj.attr[i].loc );
}
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
gl.drawElements( gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0 );
for ( var i = 0; i < bufObj.buf.length; ++ i )
gl.disableVertexAttribArray( bufObj.attr[i].loc );
gl.bindBuffer( gl.ARRAY_BUFFER, null );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
}

initScene();

})();
html,body {
height: 100%;
width: 100%;
margin: 0;
overflow: hidden;
}

#gui {
position : absolute;
top : 0;
left : 0;
}
<script id="gouraud-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec3 inPos;
attribute vec3 inNV;
attribute vec3 inCol;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

uniform mat4 u_projectionMat44;
uniform mat4 u_viewMat44;
uniform mat4 u_modelMat44;

struct TLightSource
{
vec3  lightPos;
vec3  ambient;
vec3  diffuse;
vec3  specular;
float shininess;
};

uniform TLightSource u_lightSource;

vec3 Light( vec3 eyeV, vec3 N, vec3 P )
{
vec3  lightCol  = u_lightSource.ambient;
vec3  L         = normalize( u_lightSource.lightPos-P );
float NdotL     = max( 0.0, dot( N, L ) );
lightCol       += NdotL * u_lightSource.diffuse;
vec3  H         = normalize( eyeV + L );
float NdotH     = max( 0.0, dot( N, H ) );
float kSpecular = ( u_lightSource.shininess + 2.0 ) * pow( NdotH, u_lightSource.shininess ) / ( 2.0 * 3.14159265 );
lightCol       += kSpecular * u_lightSource.specular;
return lightCol;
}

void main()
{
vec3 modelNV  = mat3( u_modelMat44 ) * normalize( inNV );
vertNV        = mat3( u_viewMat44 ) * modelNV;
vec4 modelPos = u_modelMat44 * vec4( inPos, 1.0 );
vec4 viewPos  = u_viewMat44 * modelPos;
vertPos       = viewPos.xyz / viewPos.w;
vec3 eyeV     = normalize( -vertPos );
vec3 normalV  = normalize( vertNV ) * sign(vertNV.z);
vertCol       = inCol * Light( eyeV, normalV, vertPos );
gl_Position   = u_projectionMat44 * viewPos;
}
</script>

<script id="gouraud-shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

void main()
{
gl_FragColor = vec4( vertCol, 1.0 );
}
</script>

<script id="phong-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec3 inPos;
attribute vec3 inNV;
attribute vec3 inCol;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

uniform mat4 u_projectionMat44;
uniform mat4 u_viewMat44;
uniform mat4 u_modelMat44;

void main()
{
vec3 modelNV  = mat3( u_modelMat44 ) * normalize( inNV );
vertNV        = mat3( u_viewMat44 ) * modelNV;
vertCol       = inCol;
vec4 modelPos = u_modelMat44 * vec4( inPos, 1.0 );
vec4 viewPos  = u_viewMat44 * modelPos;
vertPos       = viewPos.xyz / viewPos.w;
gl_Position   = u_projectionMat44 * viewPos;
}
</script>

<script id="phong-shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

struct TLightSource
{
vec3  lightPos;
vec3  ambient;
vec3  diffuse;
vec3  specular;
float shininess;
};

uniform TLightSource u_lightSource;

vec3 Light( vec3 eyeV, vec3 N, vec3 P )
{
vec3  lightCol  = u_lightSource.ambient;
vec3  L         = normalize( u_lightSource.lightPos - P );
float NdotL     = max( 0.0, dot( N, L ) );
lightCol       += NdotL * u_lightSource.diffuse;
vec3  H         = normalize( eyeV + L );
float NdotH     = max( 0.0, dot( N, H ) );
float kSpecular = ( u_lightSource.shininess + 2.0 ) * pow( NdotH, u_lightSource.shininess ) / ( 2.0 * 3.14159265 );
lightCol       += kSpecular * u_lightSource.specular;
return lightCol;
}

void main()
{
vec3 eyeV    = normalize( -vertPos );
vec3 normalV = normalize( vertNV ) * sign(vertNV.z);
vec3 color   = vertCol * Light( eyeV, normalV, vertPos );
gl_FragColor = vec4( color, 1.0 );
}
</script>

<form id="gui" name="inputs"><table><tr>
<td><font color= #CCF>Shading:</font></td>
<td><select id="shading">>
<option value="0">Gouraud</option>
<option value="1">Phong</option>
</select></td>
</tr><tr>
<td><font color= #CCF>Shininess:</font></td>
<td><input type="range" id="shininess" min="0" max="100" value="10"/></td>
</tr></table></form>
<canvas id="canvas" style="border: none;" width="100%" height="100%"></canvas>
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]