From f0aa3d3fb9f8f4dc25c73f1550b94e09faa80f8c Mon Sep 17 00:00:00 2001 From: lhark Date: Tue, 28 Nov 2017 12:35:49 -0500 Subject: [PATCH] Working pipeline, waves WIP --- FBO.cpp | 8 +- Packets.cpp | 60 ++++---- addPacketDisplacement.frag | 2 +- addPacketDisplacement.geom | 2 +- displayMicroMesh.frag | 56 ++++++++ displayMicroMesh.geom | 33 +++++ displayMicroMesh.vert | 36 +++++ displayTerrain.frag | 17 +++ displayTerrain.vert | 27 ++++ rasterizeWaveMeshPosition.frag | 2 - rasterizeWaveMeshPosition.vert | 4 +- ripple.cpp | 244 +++++++++++++++++++++------------ 12 files changed, 371 insertions(+), 120 deletions(-) create mode 100644 displayMicroMesh.frag create mode 100644 displayMicroMesh.geom create mode 100644 displayMicroMesh.vert create mode 100644 displayTerrain.frag create mode 100644 displayTerrain.vert diff --git a/FBO.cpp b/FBO.cpp index f0a035b..78c4abb 100644 --- a/FBO.cpp +++ b/FBO.cpp @@ -90,8 +90,10 @@ void FBO::Init( int w, int h ) // on veut des filtres de mignification et magnification de tpe NEAREST! glGenTextures(1, &m_Texture); glBindTexture(m_Target, m_Texture); - glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri( m_Target, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( m_Target, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexImage2D(m_Target, 0, GL_RGBA32F, w, h, 0, GL_RGBA, GL_FLOAT, NULL); // Créer une texture de profondeurs pour les couleurs avec L'ID m_Profondeur: @@ -99,6 +101,8 @@ void FBO::Init( int w, int h ) glBindTexture(m_Target, m_Profondeur); glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri( m_Target, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( m_Target, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexImage2D(m_Target, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); diff --git a/Packets.cpp b/Packets.cpp index 58e57a5..f4e18ca 100644 --- a/Packets.cpp +++ b/Packets.cpp @@ -127,6 +127,12 @@ Packets::Packets(int packetBudget) auto width = *reinterpret_cast(&info[18]); auto height = *reinterpret_cast(&info[22]); auto depth = *reinterpret_cast(&info[28]); + printf("Loading %s:\n", groundTexFile); + printf(" fileSize = %d\n", fileSize); + printf(" dataOffset = %d\n", dataOffset); + printf(" width = %d\n", width); + printf(" height = %d\n", height); + printf(" depth = %d\n", depth); if (info[0] != 'B' || info[1] != 'M') { fclose(f); @@ -175,16 +181,16 @@ Packets::Packets(int packetBudget) { // if we are at the boundary, intialize the distance function with 0, otherwise with maximum value if ((bound[y*m_groundSizeX + x] > 0.5f) && - ((bound[max(0, min(m_groundSizeY - 1, y + 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] <= 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 1))] <= 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y - 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] <= 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x - 1))] <= 0.5f))) + ((bound[max(0, min(m_groundSizeY - 1, y + 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] <= 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 1))] <= 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y - 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] <= 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x - 1))] <= 0.5f))) pMap[y*m_groundSizeX + x] = 0; // initialize with maximum x distance else if ((bound[y*m_groundSizeX + x] <= 0.5f) && - ((bound[max(0, min(m_groundSizeY - 1, y + 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] > 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 1))] > 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y - 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] > 0.5f) - || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x - 1))] > 0.5f))) + ((bound[max(0, min(m_groundSizeY - 1, y + 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] > 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 1))] > 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y - 1))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x + 0))] > 0.5f) + || (bound[max(0, min(m_groundSizeY - 1, y + 0))*m_groundSizeX + max(0, min(m_groundSizeX - 1, x - 1))] > 0.5f))) pMap[y*m_groundSizeX + x] = 0; // initialize with maximum x distance else pMap[y*m_groundSizeX + x] = m_groundSizeX*m_groundSizeX; // initialize with maximum x distance @@ -202,7 +208,7 @@ Packets::Packets(int packetBudget) { if (pMap[y*m_groundSizeX+x] == 0) lastBoundX = x; - pMap[y*m_groundSizeX+x] = min(pMap[y*m_groundSizeX+x], (x-lastBoundX)*(x-lastBoundX)); + pMap[y*m_groundSizeX+x] = min(pMap[y*m_groundSizeX+x], (x-lastBoundX)*(x-lastBoundX)); } } #pragma omp parallel for @@ -213,7 +219,7 @@ Packets::Packets(int packetBudget) { if (pMap[y*m_groundSizeX+x] == 0) lastBoundX = x; - pMap[y*m_groundSizeX+x] = min(pMap[y*m_groundSizeX+x], (lastBoundX-x)*(lastBoundX-x)); + pMap[y*m_groundSizeX+x] = min(pMap[y*m_groundSizeX+x], (lastBoundX-x)*(lastBoundX-x)); } } #pragma omp parallel for @@ -223,13 +229,13 @@ Packets::Packets(int packetBudget) int minDist = pMap[y*m_groundSizeX+x]; for (int yd=1; yd+y<=m_groundSizeY-1; yd++) { - minDist = min(minDist, yd*yd+pMap[(y+yd)*m_groundSizeX+x]); + minDist = min(minDist, yd*yd+pMap[(y+yd)*m_groundSizeX+x]); if (minDist < yd*yd) break; } for (int yd=-1; yd+y>=0; yd--) { - minDist = min(minDist, yd*yd+pMap[(y+yd)*m_groundSizeX+x]); + minDist = min(minDist, yd*yd+pMap[(y+yd)*m_groundSizeX+x]); if (minDist < yd*yd) break; } @@ -255,11 +261,11 @@ Packets::Packets(int packetBudget) for (int y=0; y(0,min(m_groundSizeX-1,x+1))] - m_distMap[y*m_groundSizeX + x]; - float dy = m_distMap[max(0,min(m_groundSizeY-1,y+1))*m_groundSizeX + x] - m_distMap[y*m_groundSizeX + x]; + float dx = m_distMap[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x+1))] - m_distMap[y*m_groundSizeX + x]; + float dy = m_distMap[max(0,min(m_groundSizeY-1,y+1))*m_groundSizeX + x] - m_distMap[y*m_groundSizeX + x]; Vector2f dV = Vector2f(dx,dy); - dx = m_distMap[y*m_groundSizeX + x] - m_distMap[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x-1))]; - dy = m_distMap[y*m_groundSizeX + x] - m_distMap[max(0,min(m_groundSizeY-1,y-1))*m_groundSizeX + x]; + dx = m_distMap[y*m_groundSizeX + x] - m_distMap[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x-1))]; + dy = m_distMap[y*m_groundSizeX + x] - m_distMap[max(0,min(m_groundSizeY-1,y-1))*m_groundSizeX + x]; dV += Vector2f(dx,dy); m_bndDeriv[y*m_groundSizeX+x] = Vector2f(0,0); if ((dV.x() != 0) || (dV.y() != 0)) @@ -285,7 +291,7 @@ Packets::Packets(int packetBudget) w = 4.0/16.0; else if ((abs(dy) == 0) || (abs(dx) == 0)) w = 2.0/16.0; - dV += w*m_bndDeriv[max(0,min(m_groundSizeY-1,y+dy))*m_groundSizeX + max(0,min(m_groundSizeX-1,x+dx))]; + dV += w*m_bndDeriv[max(0,min(m_groundSizeY-1,y+dy))*m_groundSizeX + max(0,min(m_groundSizeX-1,x+dx))]; } if ((dV.x() != 0) || (dV.y() != 0)) m_bndDerivH[y*m_groundSizeX+x] = dV.normalized(); @@ -303,11 +309,11 @@ Packets::Packets(int packetBudget) for (int y=0; y(0,min(m_groundSizeX-1,x+1))] - m_ground[y*m_groundSizeX + x]; - float dy = m_ground[max(0,min(m_groundSizeY-1,y+1))*m_groundSizeX + x] - m_ground[y*m_groundSizeX + x]; + float dx = m_ground[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x+1))] - m_ground[y*m_groundSizeX + x]; + float dy = m_ground[max(0,min(m_groundSizeY-1,y+1))*m_groundSizeX + x] - m_ground[y*m_groundSizeX + x]; Vector2f dV = Vector2f(dx,dy); - dx = m_ground[y*m_groundSizeX + x] - m_ground[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x-1))]; - dy = m_ground[y*m_groundSizeX + x] - m_ground[max(0,min(m_groundSizeY-1,y-1))*m_groundSizeX + x]; + dx = m_ground[y*m_groundSizeX + x] - m_ground[y*m_groundSizeX + max(0,min(m_groundSizeX-1,x-1))]; + dy = m_ground[y*m_groundSizeX + x] - m_ground[max(0,min(m_groundSizeY-1,y-1))*m_groundSizeX + x]; dV += Vector2f(dx,dy); m_gndDeriv[y*m_groundSizeX+x] = Vector2f(0,0); if ((dV.x() != 0) || (dV.y() != 0)) @@ -477,8 +483,8 @@ void Packets::DeleteGhost(int id) void Packets::CreatePacket(float pos1x, float pos1y, float pos2x, float pos2y, float dir1x, float dir1y, float dir2x, float dir2y, float k_L, float k_H, float E) { // make sure we have enough memory - if ( max(m_usedPackets, m_usedGhosts) + 10 > m_packetNum) - ExpandWavePacketMemory(max(m_usedPackets,m_usedGhosts) + PACKET_BUFFER_DELTA); + if ( max(m_usedPackets, m_usedGhosts) + 10 > m_packetNum) + ExpandWavePacketMemory(max(m_usedPackets,m_usedGhosts) + PACKET_BUFFER_DELTA); float speedDummy, kDummy; int firstfree = GetFreePackedID(); m_packet[firstfree].pos1 = Vector2f(pos1x,pos1y); @@ -957,8 +963,8 @@ void Packets::AdvectWavePackets(float dTime) // wavenumber interval subdivision if travel distance between fastest and slowest wave packets differ more than PACKET_SPLIT_DISPERSION x envelope size - if ( max(m_usedGhosts + m_usedPackets, 2*m_usedPackets) > m_packetNum) - ExpandWavePacketMemory(max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) + PACKET_BUFFER_DELTA); + if ( max(m_usedGhosts + m_usedPackets, 2*m_usedPackets) > m_packetNum) + ExpandWavePacketMemory(max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) + PACKET_BUFFER_DELTA); #pragma omp parallel for for (int uP = m_usedPackets-1; uP>=0; uP--) if (!m_packet[m_usedPacket[uP]].use3rd) @@ -1036,8 +1042,8 @@ void Packets::AdvectWavePackets(float dTime) // crest-refinement of packets of regular packet (not at any boundary, i.e. having no 3rd vertex) - if (max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) > m_packetNum) - ExpandWavePacketMemory(max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) + PACKET_BUFFER_DELTA); + if (max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) > m_packetNum) + ExpandWavePacketMemory(max(m_usedGhosts + m_usedPackets, 2 * m_usedPackets) + PACKET_BUFFER_DELTA); #pragma omp parallel for for (int uP = m_usedPackets-1; uP>=0; uP--) if (!m_packet[m_usedPacket[uP]].use3rd) diff --git a/addPacketDisplacement.frag b/addPacketDisplacement.frag index b89017b..a890321 100644 --- a/addPacketDisplacement.frag +++ b/addPacketDisplacement.frag @@ -20,7 +20,7 @@ void main(void) float centerDiff = length(In.Pos.zw - vec2(0, In.Att2.x)) - abs(In.Pos.w - In.Att2.x); float phase = -In.Att1.z + (In.Pos.w + centerDiff) * 2 * PI / In.Att1.y; /* ROLL CREDITS ! */ - vec3 ripple = (1 + cos(In.Pos.x * PI)) * (1 + cos(In.Pos.y * PI)) * In.Att1.x * + vec3 ripple = (1.0 + cos(In.Pos.x * PI)) * (1.0 + cos(In.Pos.y * PI)) * In.Att1.x * vec3(0, cos(phase), 0); Color = vec4(ripple, 1); } diff --git a/addPacketDisplacement.geom b/addPacketDisplacement.geom index 81e3d59..efd88b9 100644 --- a/addPacketDisplacement.geom +++ b/addPacketDisplacement.geom @@ -43,7 +43,7 @@ void main(void) Out.Pos = vec4(-1, -1, -In[0].Att1.w, -In[0].Att1.w); gl_Position = matrProj * matrVisu * matrModel * p2; EmitVertex(); - Out.Pos = vec4(1, 1, -In[0].Att1.w, 0); + Out.Pos = vec4(1, 1, In[0].Att1.w, 0); gl_Position = matrProj * matrVisu * matrModel * p3; EmitVertex(); Out.Pos = vec4(1, -1, In[0].Att1.w, -In[0].Att1.w); diff --git a/displayMicroMesh.frag b/displayMicroMesh.frag new file mode 100644 index 0000000..e790083 --- /dev/null +++ b/displayMicroMesh.frag @@ -0,0 +1,56 @@ +#version 410 +#define PI 3.14159265359 +#define SCENE_EXTENT 100.0f + +uniform mat4 matrModel; +uniform mat4 matrVisu; +uniform mat4 matrProj; + +uniform sampler2D terrain; +uniform sampler2D waterPos; +uniform sampler2D waterHeight; + +out vec4 Color; + +in Attribs { + vec3 pos; + vec2 texuv; +} In; + +void main(void) +{ + // the derivative of the water displacement texture gives us the water surface normal + /*TODO Linear sampler */ + vec3 pos = texture(waterPos, In.texuv).rgb + texture(waterHeight, In.texuv).rgb; + vec3 N = cross(dFdx(pos), -dFdy(pos)); + if (dot(N, N) <= 0.0) + N = vec3(0, -1, 0); + else + N = normalize(N); + vec3 V = normalize(In.pos - (matrVisu * matrModel)[3].xyz); /* TODO check view vector */ + vec3 R = V - (2 * dot(V, N))*N; /* Reflection */ + /* Diffuse + reflective lighting */ + vec3 color = vec3(0.5, 0.6, 0.8); + float fac = 1.0 - (1.0 - abs(N.y) + abs(R.y)) * (1.0 - abs(N.y) + abs(R.y)); + Color.rgb = fac * fac * color; + /* Add specular glares */ + vec3 glareDir1 = normalize(vec3(-1, -0.75, 1)); + vec3 glareDir2 = normalize(vec3( 1, -0.75, -1)); + vec3 glareDir3 = normalize(vec3( 1, -0.75, 1)); + vec3 glareDir4 = normalize(vec3(-1, -0.75, -1)); + vec3 glareDir5 = normalize(vec3( 0, -1, 0)); + Color.rgb += 100*pow(max(dot(-R, glareDir5), max(dot(-R, glareDir4), max(dot(-R, glareDir3), max(dot(-R, glareDir2), max(dot(-R, glareDir1), 0.0))))), 5000); + /* Grid overlay */ + float floorFactor = 1.0; + float sth = 0.06; + float posfac = 1.2 * 80.0 / SCENE_EXTENT; + if (fract(posfac * pos.x) < sth) + floorFactor = 0.5 - 0.5 * cos(-PI + 2.0 * PI * fract(posfac * pos.x) / sth); + if (fract(posfac * pos.z) < sth) + floorFactor = min(floorFactor, 0.5 - 0.5 * cos(-PI + 2.0 * PI * fract(posfac * pos.z) / sth)); + Color.rgb *= (0.75 + 0.25 * floorFactor); + /* TODO Linear sampling */ + float waterDepth = 1.0 + 0.9 * pow(texture(terrain, In.pos.xz / SCENE_EXTENT + vec2(0.5)).z, 4); + Color.rgb *= waterDepth; + Color.a = 1.0; +} diff --git a/displayMicroMesh.geom b/displayMicroMesh.geom new file mode 100644 index 0000000..2b0b61c --- /dev/null +++ b/displayMicroMesh.geom @@ -0,0 +1,33 @@ +#version 410 +#define SCENE_EXTENT 100.0f + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +uniform mat4 matrModel; +uniform mat4 matrVisu; +uniform mat4 matrProj; + +///////////////////////////////////////////////////////////////// + +in Attribs { + vec3 pos; + vec2 texuv; +} In[]; + +out Attribs { + vec3 pos; + vec2 texuv; +} Out; + +void main(void) +{ + if (gl_in[0].gl_Position.w<0.01 || gl_in[1].gl_Position.w<0.01 || gl_in[2].gl_Position.w<0.01) + return; + for (int i = 0; i < 3; i++) { + Out.pos = In[i].pos; + Out.texuv = In[i].texuv; + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } +} diff --git a/displayMicroMesh.vert b/displayMicroMesh.vert new file mode 100644 index 0000000..24fccfc --- /dev/null +++ b/displayMicroMesh.vert @@ -0,0 +1,36 @@ +#version 410 +#define SCENE_EXTENT 100.0f + +uniform mat4 matrModel; +uniform mat4 matrVisu; +uniform mat4 matrProj; + +uniform sampler2D terrain; +uniform sampler2D waterPos; +uniform sampler2D waterHeight; + +///////////////////////////////////////////////////////////////// + +layout(location=0) in vec2 Vertex; + +out Attribs { + vec3 pos; + vec2 texuv; +} Out; + +// takes a simple 2D vertex on the ground plane, offsets it along y by the land or water offset and projects it on screen +void main(void) +{ + Out.texuv = Vertex; + /* TODO setup Linear sampler */ + vec4 pos = texture(waterPos, Vertex); + if (pos.w <= 0.0) { /* No position data -> no water here */ + Out.pos = vec3(0); + gl_Position = vec4(0,0,0,-1); + } else { + /* TODO setup Linear sampler */ + Out.pos = pos.xyz + texture(waterHeight, Vertex).rgb; + gl_Position = matrProj * matrVisu * matrModel * vec4(Out.pos, 1); + } +} + diff --git a/displayTerrain.frag b/displayTerrain.frag new file mode 100644 index 0000000..6ee46c1 --- /dev/null +++ b/displayTerrain.frag @@ -0,0 +1,17 @@ +#version 410 +#define PI 3.14159265359 + +out vec4 Color; + +in Attribs { + vec3 pos; +} In; + +void main(void) +{ + if (In.pos.y < - 0.1) + discard; /* Fragment underwater */ + Color.rgb = (0.25 + 0.75 * In.pos.y) * vec3(0.75); + Color.a = 1.0; +} + diff --git a/displayTerrain.vert b/displayTerrain.vert new file mode 100644 index 0000000..d9ec767 --- /dev/null +++ b/displayTerrain.vert @@ -0,0 +1,27 @@ +#version 410 +#define SCENE_EXTENT 100.0f + +uniform mat4 matrModel; +uniform mat4 matrVisu; +uniform mat4 matrProj; + +uniform sampler2D terrain; + +///////////////////////////////////////////////////////////////// + +layout(location=0) in vec2 Vertex; + +out Attribs { + vec3 pos; +} Out; + +// takes a simple 2D vertex on the ground plane, offsets it along y by the land or water offset and projects it on screen +void main(void) +{ + vec2 uv = 0.5 * (Vertex + 1); + float h = 0.001 * (-3.5 + 80 * texture(terrain, uv).r); + vec3 pos = SCENE_EXTENT * 0.5 * vec3(Vertex.x, h, Vertex.y); + Out.pos = pos; + gl_Position = matrProj * matrVisu * matrModel * vec4(pos, 1); +} + diff --git a/rasterizeWaveMeshPosition.frag b/rasterizeWaveMeshPosition.frag index be379b0..e648c65 100644 --- a/rasterizeWaveMeshPosition.frag +++ b/rasterizeWaveMeshPosition.frag @@ -1,7 +1,5 @@ #version 410 -uniform sampler2D tex; - in Attribs { vec3 pos; } In; diff --git a/rasterizeWaveMeshPosition.vert b/rasterizeWaveMeshPosition.vert index 971d7ff..841963f 100644 --- a/rasterizeWaveMeshPosition.vert +++ b/rasterizeWaveMeshPosition.vert @@ -16,7 +16,7 @@ out Attribs { void main(void) { - Out.pos = 0.5 * SCENE_EXTENT * vec3(Vertex.x, Vertex.y, 0); - gl_Position = matrProj * matrVisu * vec4(Out.pos, 1.); + Out.pos = 0.5 * SCENE_EXTENT * vec3(Vertex.x, 0, Vertex.y); + gl_Position = matrProj * matrVisu * matrModel * vec4(Out.pos, 1.); } diff --git a/ripple.cpp b/ripple.cpp index 909b7d1..2021431 100644 --- a/ripple.cpp +++ b/ripple.cpp @@ -42,7 +42,6 @@ GLint locmatrModelRWMP = -1; GLint locmatrVisuRWMP = -1; GLint locmatrProjRWMP = -1; GLint locmatrNormaleRWMP = -1; -GLint locTexRWMP = -1; // Locations for AddPacketDisplacement shader GLuint locPosAPD = -1; GLuint locAtt1APD = -1; @@ -65,14 +64,15 @@ GLuint locTexCoordDMM = -1; GLuint locmatrModelDMM = -1; GLuint locmatrVisuDMM = -1; GLuint locmatrProjDMM = -1; -GLuint locTexDMM = -1; +GLuint locTerrainTexDMM = -1; +GLuint locWaterPosTexDMM = -1; +GLuint locWaterHeightTexDMM = -1; // Locationss for DisplayTerrain shader GLuint locVertexDT = -1; -GLuint locTexCoordDT = -1; GLuint locmatrModelDT = -1; GLuint locmatrVisuDT = -1; GLuint locmatrProjDT = -1; -GLuint locTexDT = -1; +GLuint locTerrainTexDT = -1; // Locations for RenderAA shader GLuint locVertexRAA = -1; GLuint locTexCoordRAA = -1; @@ -95,13 +95,16 @@ GLint locmatrProjBase = -1; GLuint vao[NB_SHADERS]; GLuint vbo[5]; GLuint ubo[4]; -GLuint vbosQuad[2]; +GLuint vbosQuad[2]; /* Vertex & Tex Coord */ GLuint vboPacket; +GLuint vboHeightField; +GLuint vboDMM[2]; /* Vertex & Index */ // matrices de du pipeline graphique MatricePipeline matrModel; MatricePipeline matrVisu; MatricePipeline matrProj; +MatricePipeline matrProjWide; // les formes FormeSphere *sphere = NULL, *sphereLumi = NULL; @@ -126,6 +129,10 @@ FBO *posFBO; FBO *heightFBO; FBO *aaFBO; +// Terrain mesh size +const int terrainW = 1024; +const int terrainH = 1024; + // Wave Packets Packets *packets; int packetBudget = 10000; @@ -135,6 +142,8 @@ int packetBudget = 10000; * vec4: for rendering x = center of wave bending circle*/ GLfloat packetData[PACKET_GPU_BUFFER_SIZE * 3 * 4]; +int nIndexDMM = 0; + //////////////////////////////////////// // déclaration des variables globales // //////////////////////////////////////// @@ -210,6 +219,8 @@ struct /* Forward declarations */ void displayPacketOutlined(int count); void addPacketDisplacement(int count); +void displayTerrain(); +void displayMicroMesh(); void verifierAngles() @@ -259,6 +270,7 @@ void updatePackets() // TODO Setup wide projection for InitiateWaveField (RasterizeWaveMeshPosition) + heightFBO->CommencerCapture(); int displayedPackets = 0; int packetChunk =0; /* Standard wave packets */ @@ -279,7 +291,9 @@ void updatePackets() packetData[packetChunk++] = packets->m_packet[pk].envelope; /* Att2 */ packetData[packetChunk++] = packets->m_packet[pk].bending; - packetChunk += 3; /* The last 3 elements aren't needed */ + packetData[packetChunk++] = 0.0; + packetData[packetChunk++] = 0.0; + packetData[packetChunk++] = 0.0; displayedPackets++; if (packetChunk >= PACKET_GPU_BUFFER_SIZE * 3 * 4) { glBindBuffer(GL_ARRAY_BUFFER, vboPacket); @@ -310,7 +324,9 @@ void updatePackets() packetData[packetChunk++] = packets->m_ghostPacket[pk].envelope; /* Att2 */ packetData[packetChunk++] = packets->m_ghostPacket[pk].bending; - packetChunk += 3; /* The last 3 elements aren't needed */ + packetData[packetChunk++] = 0.0; + packetData[packetChunk++] = 0.0; + packetData[packetChunk++] = 0.0; displayedPackets++; if (packetChunk >= PACKET_GPU_BUFFER_SIZE * 3 * 4) { glBindBuffer(GL_ARRAY_BUFFER, vboPacket); @@ -328,6 +344,7 @@ void updatePackets() //displayPacketOutlined(packetChunk / 12); /* TODO EvaluatePackets(packetChunk) */ addPacketDisplacement(packetChunk / 12); + heightFBO->TerminerCapture(); /* TODO DisplayScene */ /* TODO Get camera center */ } @@ -448,7 +465,6 @@ void chargerNuanceurs() locmatrModelRWMP = getloc( progRasterizeWaveMeshPosition, "matrModel" , LocUniform); locmatrVisuRWMP = getloc( progRasterizeWaveMeshPosition, "matrVisu" , LocUniform); locmatrProjRWMP = getloc( progRasterizeWaveMeshPosition, "matrProj" , LocUniform); - locTexRWMP = getloc( progRasterizeWaveMeshPosition, "tex" , LocUniform); } // Load AddPacketDisplacement shader @@ -488,7 +504,9 @@ void chargerNuanceurs() locmatrModelDMM = getloc( progDisplayMicroMesh, "matrModel" , LocUniform); locmatrVisuDMM = getloc( progDisplayMicroMesh, "matrVisu" , LocUniform); locmatrProjDMM = getloc( progDisplayMicroMesh, "matrProj" , LocUniform); - locTexDMM = getloc( progDisplayMicroMesh, "tex" , LocUniform); + locTerrainTexDMM = getloc( progDisplayMicroMesh, "terrain" , LocUniform); + locWaterPosTexDMM = getloc( progDisplayMicroMesh, "waterPos" , LocUniform); + locWaterHeightTexDMM = getloc( progDisplayMicroMesh, "waterHeight" , LocUniform); } // Load DisplayTerrain shader @@ -496,11 +514,10 @@ void chargerNuanceurs() const GLchar *shaders[3] = {"displayTerrain.vert", NULL, "displayTerrain.frag"}; progDisplayTerrain = createShader(shaders); locVertexDT = getloc( progDisplayTerrain, "Vertex" , LocAttrib); - locTexCoordDT = getloc( progDisplayTerrain, "TexCoord" , LocAttrib); locmatrModelDT = getloc( progDisplayTerrain, "matrModel" , LocUniform); locmatrVisuDT = getloc( progDisplayTerrain, "matrVisu" , LocUniform); locmatrProjDT = getloc( progDisplayTerrain, "matrProj" , LocUniform); - locTexDT = getloc( progDisplayTerrain, "tex" , LocUniform); + locTerrainTexDT = getloc( progDisplayTerrain, "terrain" , LocUniform); } // Load RenderAA shader @@ -588,6 +605,40 @@ void initPacketMesh() } +void initHeightFieldMesh() +{ + GLfloat *data = new GLfloat[terrainW * terrainH * 6 * 2]; + /* TODO Benchmark usefullness of parallel for */ + #pragma omp parallel for + for (int y=0; yGetRGBTex()); + glUniform1i(locWaterPosTexDMM, 1); + glActiveTexture(GL_TEXTURE0 + 2); + glBindTexture(GL_TEXTURE_2D, heightFBO->GetRGBTex()); + glUniform1i(locWaterHeightTexDMM, 2); + + glDrawElements(GL_TRIANGLES, nIndexDMM, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); + glUseProgram(0); +} + + void afficherModele() { // Dessiner le modèle @@ -702,40 +786,17 @@ void afficherModele() // mise à l'échelle matrModel.Scale( 5.0, 5.0, 5.0 ); - glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel ); + posFBO->CommencerCapture(); + rasterizeWaveMeshPosition(); + posFBO->TerminerCapture(); + updatePackets(); + displayTerrain(); + displayMicroMesh(); + // displayTerrain(); } matrModel.PopMatrix(); } -void afficherLumiere() -{ - // Dessiner la lumiere - - // tracer une ligne vers la source lumineuse - const GLfloat fact = 5.; - GLfloat coords[] = - { - LightSource[0].position.x , LightSource[0].position.y , LightSource[0].position.z, - LightSource[0].position.x+LightSource[0].spotDirection.x/fact, LightSource[0].position.y+LightSource[0].spotDirection.y/fact, LightSource[0].position.z+LightSource[0].spotDirection.z/fact - }; - glLineWidth( 3.0 ); - glVertexAttrib3f( locColorBase, 1.0, 1.0, 0.5 ); // jaune - glBindVertexArray( vao[1] ); - matrModel.PushMatrix(); { - glBindBuffer( GL_ARRAY_BUFFER, vbo[4] ); - glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(coords), coords ); - glDrawArrays( GL_LINES, 0, 2 ); - } matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel ); - glBindVertexArray( 0 ); - glLineWidth( 1.0 ); - - // tracer la source lumineuse - matrModel.PushMatrix(); { - matrModel.Translate( LightSource[0].position.x, LightSource[0].position.y, LightSource[0].position.z ); - glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel ); - sphereLumi->afficher(); - } matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel ); -} // fonction d'affichage void FenetreTP::afficherScene() @@ -746,43 +807,20 @@ void FenetreTP::afficherScene() glUseProgram( progBase ); // définir le pipeline graphique - if ( enPerspective ) - { - matrProj.Perspective( 35.0, (GLdouble)largeur_ / (GLdouble)hauteur_, - 0.1, 300.0 ); - } - else - { - const GLfloat d = 8.0; - if ( largeur_ <= hauteur_ ) - { - matrProj.Ortho( -d, d, - -d*(GLdouble)hauteur_ / (GLdouble)largeur_, - d*(GLdouble)hauteur_ / (GLdouble)largeur_, - 0.1, 300.0 ); - } - else - { - matrProj.Ortho( -d*(GLdouble)largeur_ / (GLdouble)hauteur_, - d*(GLdouble)largeur_ / (GLdouble)hauteur_, - -d, d, - 0.1, 300.0 ); - } - } + matrProj.Perspective( 45.0, (GLdouble)largeur_ / (GLdouble)hauteur_, 0.5, 4000.0 ); + matrProjWide.Perspective( 60.0, (GLdouble)largeur_ / (GLdouble)hauteur_, 0.1, 15000.0 ); glUniformMatrix4fv( locmatrProjBase, 1, GL_FALSE, matrProj ); - matrVisu.LookAt( 0.0, 3.0, distCam, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); + //matrVisu.LookAt( 0.0, 3.0, distCam, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); + matrVisu.LookAt( 10.17, 22.13, 59.49, 10.17, 21.66, 58.61, 0.0, 1.0, 0.0 ); + glUniformMatrix4fv( locmatrVisuBase, 1, GL_FALSE, matrVisu ); matrModel.LoadIdentity(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel ); // afficher les axes - if ( afficheAxes ) FenetreTP::afficherAxes( 8.0 ); - - // dessiner la scène - //glActiveTexture( GL_TEXTURE0 ); // activer la texture '0' (valeur de défaut) - glUniform1i( loclaTexture, 0 ); // '0' => utilisation de GL_TEXTURE0 + if ( afficheAxes ) FenetreTP::afficherAxes( 1.0 ); afficherModele(); } @@ -793,13 +831,49 @@ void FenetreTP::redimensionner( GLsizei w, GLsizei h ) std::cout << "Resizing to " << w << "×" << h << std::endl; /* FIXME Is this function called on program start ? */ glViewport( 0, 0, w, h ); - /* TODO Create/resize display mesh */ posFBO->Liberer(); posFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h); heightFBO->Liberer(); heightFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h); aaFBO->Liberer(); aaFBO->Init(AA_OVERSAMPLE_FACTOR * w, AA_OVERSAMPLE_FACTOR * h); + + /* Create/resize display mesh */ + int meshW = WAVEMESH_WIDTH_FACTOR * w; /*Ça fait un gros mouton */ + int meshH = WAVEMESH_HEIGHT_FACTOR * h; + GLfloat *mesh = new GLfloat[meshW * meshH * 2]; + nIndexDMM = 3 * 2 * (meshW - 1) * (meshH -1); + GLuint *index = new GLuint[nIndexDMM]; + #pragma omp parallel for + for (int y = 0; y < meshH; ++y) { + for (int x = 0; x < meshW; ++x) { + mesh[(y * meshW + x) * 2 + 0] = (x + 0.5) / meshW; + mesh[(y * meshW + x) * 2 + 1] = (y + 0.5) / meshH; + } + } + #pragma omp parallel for + for (int y = 0; y < meshH - 1; ++y) { + for (int x = 0; x < meshW - 1; ++x) { + index[(y * (meshW - 1) + x) * 6 + 0] = y * meshW + x; + index[(y * (meshW - 1) + x) * 6 + 1] = y * meshW + x + 1; + index[(y * (meshW - 1) + x) * 6 + 2] = (y + 1) * meshW + x; + index[(y * (meshW - 1) + x) * 6 + 3] = y * meshW + x + 1; + index[(y * (meshW - 1) + x) * 6 + 4] = (y + 1) * meshW + x + 1; + index[(y * (meshW - 1) + x) * 6 + 5] = (y + 1) * meshW + x; + } + } + glGenBuffers(2, vboDMM); + glBindVertexArray(vao[DMM_SHADER]); + glBindBuffer(GL_ARRAY_BUFFER, vboDMM[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * meshW * meshH * 2, mesh, GL_STATIC_DRAW); + glVertexAttribPointer(locVertexDMM, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(locVertexDMM); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboDMM[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * nIndexDMM, index, GL_STATIC_DRAW); + glBindVertexArray(0); + + delete [] mesh; + delete [] index; } static void echoEtats( )