OpenGL Convert NV12 to RGB24 using shader - opengl

I tried to write an application to display YUV image in OpenGL. I was successfully converted YUV to RGB in C++ using this snippet (source)
static long int crv_tab[256];
static long int cbu_tab[256];
static long int cgu_tab[256];
static long int cgv_tab[256];
static long int tab_76309[256];
static unsigned char clp[1024]; //for clip in CCIR601
void init_yuv420p_table()
{
long int crv,cbu,cgu,cgv;
int i,ind;
static int init = 0;
if (init == 1) return;
crv = 104597; cbu = 132201; /* fra matrise i global.h */
cgu = 25675; cgv = 53279;
for (i = 0; i < 256; i++)
{
crv_tab[i] = (i-128) * crv;
cbu_tab[i] = (i-128) * cbu;
cgu_tab[i] = (i-128) * cgu;
cgv_tab[i] = (i-128) * cgv;
tab_76309[i] = 76309*(i-16);
}
for (i = 0; i < 384; i++)
clp[i] = 0;
ind = 384;
for (i = 0;i < 256; i++)
clp[ind++] = i;
ind = 640;
for (i = 0;i < 384; i++)
clp[ind++] = 255;
init = 1;
}
void yuv420sp_to_rgb24(YUV_TYPE type, unsigned char* yuvbuffer,unsigned char* rgbbuffer, int width,int height)
{
int y1, y2, u, v;
unsigned char *py1, *py2;
int i, j, c1, c2, c3, c4;
unsigned char *d1, *d2;
unsigned char *src_u;
static int init_yuv420p = 0;
src_u = yuvbuffer + width * height; // u
py1 = yuvbuffer; // y
py2 = py1 + width;
d1 = rgbbuffer;
d2 = d1 + 3 * width;
init_yuv420p_table();
for (j = 0; j < height; j += 2)
{
for (i = 0; i < width; i += 2)
{
if (type == FMT_NV12)
{
u = *src_u++;
v = *src_u++; // v紧跟u,在u的下一个位置
}
if (type == FMT_NV21)
{
v = *src_u++;
u = *src_u++; // u紧跟v,在v的下一个位置
}
c1 = crv_tab[v];
c2 = cgu_tab[u];
c3 = cgv_tab[v];
c4 = cbu_tab[u];
//up-left
y1 = tab_76309[*py1++];
*d1++ = clp[384+((y1 + c1)>>16)];
*d1++ = clp[384+((y1 - c2 - c3)>>16)];
*d1++ = clp[384+((y1 + c4)>>16)];
//down-left
y2 = tab_76309[*py2++];
*d2++ = clp[384+((y2 + c1)>>16)];
*d2++ = clp[384+((y2 - c2 - c3)>>16)];
*d2++ = clp[384+((y2 + c4)>>16)];
//up-right
y1 = tab_76309[*py1++];
*d1++ = clp[384+((y1 + c1)>>16)];
*d1++ = clp[384+((y1 - c2 - c3)>>16)];
*d1++ = clp[384+((y1 + c4)>>16)];
//down-right
y2 = tab_76309[*py2++];
*d2++ = clp[384+((y2 + c1)>>16)];
*d2++ = clp[384+((y2 - c2 - c3)>>16)];
*d2++ = clp[384+((y2 + c4)>>16)];
}
d1 += 3*width;
d2 += 3*width;
py1 += width;
py2 += width;
}
}
In order to make my application runs smoother, instead of doing the conversion on the CPU, I do it in the fragment shader.
I separate the YUV buffer into Y_Buffer[width*height], U_Buffer[width*height/4] and V_Buffer[width*height/4] from the interleaved UV_Buffer[width*height/2] and pass it to the fragment shader. (I intended to pass the Y_Buffer and the UV_Buffer with the type format GL_RED and GL_RG respectively by using glTexImage2D but somehow when I read the G channel of the UV_Texture in the fragment shader, it always returns 0).
Below is the conversion in the fragment shader:
uniform sampler2D textureY;
uniform sampler2D textureU;
uniform sampler2D textureV;
void main() {
vec3 yuv, rgb;
vec3 yuv2r = vec3(1.164, 0.0, 1.596);
vec3 yuv2g = vec3(1.164, -0.391, -0.813);
vec3 yuv2b = vec3(1.164, 2.018, 0.0);
yuv.x = texture(textureY, texCoord).r - 0.0625;
yuv.y = texture(textureU, texCoord).r - 0.5;
yuv.z = texture(textureV, texCoord).r - 0.5;
rgb.x = dot(yuv, yuv2r);
rgb.y = dot(yuv, yuv2g);
rgb.z = dot(yuv, yuv2b);
FragColor = vec4(rgb, 1.0);
}
But all I got is green and pink pixels. I'm quite a newbie in OpenGL. Can anyone point out where I may be wrong? Your help is appreciated.
Update: Add codes that load texture
FILE fp = fopen("nv21.raw", "rb");
unsigned char *yuvBuffer = new unsigned char[width*height*3/2];
fread(yuvBuffer, 1, width*height*3/2, fp);
unsigned char *vuBuffer = &yuvBuffer[width*height];
int bufSize = width*height/4;
unsigned char *uBuffer = new unsigned char[bufSize];
memset(uBuffer, 0, bufSize);
unsigned char *vBuffer = new unsigned char[bufSize];
memset(vBuffer, 0, bufSize);
unsigned char *uPtr, *vPtr;
uPtr = uBuffer;
vPtr = vBuffer;
for (int i = 0; i < bufSize; i++)
{
*vPtr = *vuBuffer++;
*uPtr = *vuBuffer++;
}
GLuint textureID[3];
glGenTextures(1, &textureID[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, &yuvBuffer[0]);
glBindTexture(0);
glGenTextures(1, &textureID[1]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, uBuffer);
glBindTexture(0);
glGenTextures(1, &textureID[2]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textureID[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, vBuffer);
glBindTexture(0);

By default the texture samplers in the shader program are associated to texture unit 0 (default value is 0).
You have to assign the index of the texture unit to the texture sampler uniforms, by glUniform1i. The texture unit is the binding point between the Sampler and the Texture object. e.g.:
GLint locTexY = glGetUniformLocation(program, "textureY");
GLint locTexU = glGetUniformLocation(program, "textureU");
GLint locTexV = glGetUniformLocation(program, "textureV");
glUseProgram(program);
glUniform1i(locTexY, 0); // corresponds to GL_TEXTURE0
glUniform1i(locTexU, 1); // corresponds to GL_TEXTURE1
glUniform1i(locTexV, 2); // corresponds to GL_TEXTURE2
Since OpenGL 4.20, the Binding points can be set in-shader by Layout Qualifier:
layout(binding = 0) uniform sampler2D textureY;
layout(binding = 1) uniform sampler2D textureU;
layout(binding = 2) uniform sampler2D textureV;

Related

Compute shader can't get result image

I am using the compute shader to get a column of colors to match the conditions and I want to get the results for further processing. I want to get the output data in image1D imgOutput, but get_img can't get anything, did I do something wrong?
the texture in the first block has been generated before.
Shader spriteRowProgram, spriteColumnProgram;
unsigned int resultTexture = 0;
const std::string path = found::utils::Environment::GetRunPath();
const std::string sprite_row_path = path + "shaders/glfw_sprite_row.comp";
spriteRowProgram = Shader(sprite_row_path);
std::vector<GLfloat> get_img(qMax(TEX_WIDTH, TEX_HEIGHT) * 4);
glGenTextures(1, &resultTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, resultTexture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, qMax(TEX_WIDTH, TEX_HEIGHT), 0, GL_RGBA, GL_FLOAT, get_img.data());
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture);
spriteRowProgram.use();
glUniform1i(1, 1);
glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
glUniform1i(0, 0);
glBindImageTexture(0, resultTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
glClear(GL_COLOR_BUFFER_BIT);
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, location = 0, binding = 0) uniform writeonly image1D imgOutput;
// texture samplers
layout(rgba32f, location = 1, binding = 1) uniform readonly image2D inputImage;
uniform int input_width;
uniform int input_height;
void main()
{
vec4 baseColor = imageLoad(inputImage, ivec2(0, 0));
bool alpha = baseColor.w == 1;
bool success = true;
for (int i = 0; i <= input_height; ++i)
{
vec4 current = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x, i));
if (alpha) {
if (current.w > 0.99) continue;
else {
success = false;
break;
}
} else {
vec4 difference = baseColor - current;
success = abs(difference.x) < 0.01 && abs(difference.y) < 0.01 && abs(difference.z) < 0.01;
if (success) continue;
else {
break;
}
}
}
if (success) baseColor = ivec4(0.1, 0.1, 0.1, 0.1);
else baseColor = ivec4(1.0, 1.0, 1.0, 1.0);
imageStore(imgOutput, int(gl_GlobalInvocationID.x), baseColor);
}
One issue might be that if you want to access images after the compute shader, the argument for glMemoryBarrier should be GL_SHADER_IMAGE_ACCESS_BARRIER_BIT and not GL_SHADER_STORAGE_BARRIER_BIT.
So
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
should really be
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

How to use GL_TEXTURE_2D_ARRAY with stb_image

I'm trying to create sprite animation with texture array. Right now I have follow code:
int width, height, depth;
stbi_set_flip_vertically_on_load(true);
byte_t* buffer = stbi_load(R"(.\fire.jpg)",
&width, &height, &depth, STBI_rgb_alpha);
if (buffer == nullptr) {
std::cerr << "Could not read texture" << std::endl;
return EXIT_FAILURE;
}
GLuint texture_id;
const GLenum target = GL_TEXTURE_2D_ARRAY;
SAFE_CALL(glGenTextures(1, &texture_id));
SAFE_CALL(glBindTexture(target, texture_id));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
const GLsizei tile_w_count = 6, tile_h_count = 6;
const GLsizei total_tiles = tile_w_count * tile_h_count;
const GLsizei tile_w = width / tile_w_count,
tile_h = height / tile_h_count;
std::cout << "Texture WxH: " << width << "x" << height;
std::cout << ", Tile WxH: " << tile_w << "x" << tile_h << std::endl;
SAFE_CALL(glTexStorage3D(target, 1, GL_RGBA8, tile_w, tile_h,
total_tiles));
SAFE_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, width));
SAFE_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, height));
for (GLsizei i = 0; i < total_tiles; ++i) {
SAFE_CALL(glTexSubImage3D(
GL_TEXTURE_2D_ARRAY,
0,
0, 0, i,
tile_w, tile_h, 1,
GL_RGBA,
GL_UNSIGNED_BYTE,
buffer + (i * tile_w * tile_h * depth)
));
}
Fragment shader:
#version 460 core
in vec2 tex_coords;
out vec4 frag_color;
uniform sampler2DArray texture_0;
uniform int current_frame;
uniform int total_frames;
float actual_layer() {
return max(0, min(total_frames - 1,
floor(current_frame + 0.5)));
}
void main() {
frag_color = texture(texture_0, vec3(tex_coords, actual_layer()));
}
And seems like I incorrectly crop source texture, because when I run my program in Nsight debugger I saw follow:
Texture array:
Original image:
Is it issue with cropping source image, or issue with fragment shader? How to make sprite animation correctly?
You calculate the data offset incorrectly. The correct way would be:
Convert i to a 2-d index of the tile:
int ix = i % tile_w_count;
int iy = i / tile_w_count;
The x and y coordinates of its top-left pixel would be at
int x = ix*tile_w;
int y = iy*tile_h;
The offset can be calculated then by:
buffer + 4*(y*width + x)
Note that you shall use 4 instead of depth because stb returns the number of channels that was found in the file rather the number of the channels returned.

Heap corruption from this method

I'm getting a heap corruption error whenever the following method is called:
bool TextureData::loadFromMemory(char* memData, int w, int h)
{
GLuint texId;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texId);
glTextureId = static_cast<int>(texId);
glBindTexture(GL_TEXTURE_2D, texId); // Bind the texture
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
memWidth = width = w;
memHeight = height = h;
int newPad = 0;//(4 - (w*4)%4)==4 ? 0 : (4 - (w*4)%4);
int oldPad = 0;//(4 - (w*3)%4)==4 ? 0 : (4 - (w*3)%4);
size_t size = (width+newPad)*height * 4;
char* data = 0;
data = new char[size];
memcpy(data, memData, size * sizeof(char));
// Texture generation
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, memWidth, memHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
delete [] data;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return true;
}
Where the char* data array given to this method is generated like this:
int imageSize = width_ * height_ * 4;
data_ = new char[imageSize];
SDL_LockSurface(TextureImage);
for (Uint y = 0; y < height_; ++y)
{
for (Uint x = 0; x < width_; ++x)
{
size_t currPixel = (y * width_ + x) * 4;
SDL_Color rgb;
Uint32 data = getPixel(TextureImage, x, y);
SDL_GetRGB(data, TextureImage->format, &rgb.r, &rgb.g, &rgb.b);
data_[currPixel] = (char)rgb.r;
data_[currPixel + 1] = (char)rgb.g;
data_[currPixel + 2] = (char)rgb.b;
data_[currPixel + 3] = (char)255;
}
}
SDL_UnlockSurface(TextureImage);
SDL_FreeSurface(TextureImage);
I can't figure out why the loadFromMemory method is causing a heap corruption and need a review, if anyone has any ideas.

LWJGL/OpenGL Why are there dots on the edge of my texture when i map it onto half-sphere or sphere?

What is causing these dots (in some cases it's a line, it depends on camera angle) to appear on the edge of my texture that i map on a half-sphere or sphere? When i map the same texture on a half-cylinder it works fine, there are no dots (line).
This is how it looks:
This is how i set my texture params:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
This is how i draw my half-sphere:
float x, y, z;
float s, t;
double alpha1, alpha2, beta;
for(double j = 0; j < gradation; j++) {
alpha1 = j/gradation * Math.PI;
alpha2 = (j+1)/gradation * Math.PI;
for(double i = 0; i <= gradation; i++) {
beta = i/gradation * Math.PI;
z = (float) (Math.sin(alpha1)*Math.cos(beta));
x = (float) (Math.sin(alpha1)*Math.sin(beta));
y = (float) Math.cos(alpha1);
s = (float) (beta / Math.PI);
t = (float) (alpha1 / Math.PI);
posCoords[3*newVertexIndex] = x*radius;
posCoords[3*newVertexIndex + 1] = y*radius;
posCoords[3*newVertexIndex + 2] = z*radius;
texCoords[2*newVertexIndex] = s;
texCoords[2*newVertexIndex + 1] = t;
indices[vertexCounter++] = newVertexIndex++;
z = (float) (Math.sin(alpha2)*Math.cos(beta));
x = (float) (Math.sin(alpha2)*Math.sin(beta));
y = (float) Math.cos(alpha2);
t = (float) (alpha2 / Math.PI);
posCoords[3*newVertexIndex] = x*radius;
posCoords[3*newVertexIndex + 1] = y*radius;
posCoords[3*newVertexIndex + 2] = z*radius;
texCoords[2*newVertexIndex] = s;
texCoords[2*newVertexIndex + 1] = t;
indices[vertexCounter++] = newVertexIndex++;
}
}
I finally managed to resolve this. Issue was that I used single GL_TRIANGLE_STRIP to draw my half-sphere, which can't be used if the shared vertices have different texture coordinates, in that case you need to use GL_TRIANGLES. I found out about this on this site.

Repeating OpenGL-es texture bound to hills in cocos2d 3.2

ORIGINAL ARTICLE
I am in the process of trying to implement raywenderlich's tutorial on generating hills with repeating striped coordinates using cocos2d, This article was written for Cocos2D, and as I am trying to port it to Cocos2Dx 3.2 This means updating it for openGl-es 2. So far everything has worked perfectly, However I am having problems with getting the texture of the hill to repeat properly and also after some repeatation the texture start degrade ...
please help me to get texture properly.......
Here is my code:
#define Point_FROM_B2VEC(v) Point((v.x*PTM_RATIO),(v.y*PTM_RATIO))
#define B2VEC_FROM_Point(v) b2Vec2(v.x/PTM_RATIO,v.y/PTM_RATIO)
#define PTM_RATIO 32
#define MAX_HILL_POINTS 15
#define MAX_SEGMENTS MAX_HILL_POINTS*10
#define MAX_COORDINATES 600
Point hillTopVertices[MAX_COORDINATES],hillBottomVertices[MAX_COORDINATES];
Point hillTopTexCoords[MAX_COORDINATES];
Point hillBottomTexCoords[MAX_COORDINATES];
GLuint terraintopTexId, terrainBottomTexId;
float terrainTopTexSize, terrainBottomTexSize;
Sending the hills the texture:
texture = Director::getInstance()->getTextureCache()->addImage("surface.png");
terraintopTexId = texture->getName();
terrainTopTexSize = texture->getPixelsWide()/2;
//terrain top texture
texture1 = Director::getInstance()->getTextureCache()->addImage("old_stone_wall_textures_v3_3000x2000_1.jpg");
terrainBottomTexId = texture1->getName();
terrainBottomTexSize = texture1->getPixelsWide()/2;
void Terrain::generateCoordinates()
{
int nTopVertCount = 0;
int nTopVertCount1 = 0;
//get the hill vertex and texcoordinates
for(short i = 0; i < MAX_SEGMENTS; ++i)
{
Point point1 = Point_FROM_B2VEC(vertices[i]);
Point point2 = Point_FROM_B2VEC(vertices[i+1]);
CCLOG("%f",terrainBottomTexSize);
hillTopVertices[nTopVertCount1] = Point(point1.x, point1.y+16);
hillTopTexCoords[nTopVertCount1++] = Point(point1.x/terrainTopTexSize, 1);
hillTopVertices[nTopVertCount1] = Point(point2.x, point2.y+16);
hillTopTexCoords[nTopVertCount1++] = Point(point2.x/terrainTopTexSize, 1);
hillTopVertices[nTopVertCount1] = Point(point1.x, point1.y-16);
hillTopTexCoords[nTopVertCount1++] = Point(point1.x/terrainTopTexSize, 0);
hillTopVertices[nTopVertCount1] = Point(point2.x, point2.y-16);
hillTopTexCoords[nTopVertCount1++] = Point(point2.x/terrainTopTexSize, 0);
}
for(short i = 0; i < MAX_SEGMENTS; ++i)
{
Point point1 = Point_FROM_B2VEC(vertices[i]);
Point point2 = Point_FROM_B2VEC(vertices[i+1]);
hillBottomVertices[nTopVertCount] = Point(point1.x, point1.y-terrainBottomTexSize+1);
hillBottomTexCoords[nTopVertCount++] = Point(point1.x/terrainBottomTexSize, 1);
hillBottomVertices[nTopVertCount] = Point(point2.x, point2.y-terrainBottomTexSize+1);
hillBottomTexCoords[nTopVertCount++] = Point(point2.x/terrainBottomTexSize, 1);
hillBottomVertices[nTopVertCount] = Point(point1.x, point1.y+2);
hillBottomTexCoords[nTopVertCount++] = Point(point1.x/terrainBottomTexSize, 0);
hillBottomVertices[nTopVertCount] = Point(point2.x, point2.y+2);
hillBottomTexCoords[nTopVertCount++] = Point(point2.x/terrainBottomTexSize, 0);
}
//energy adding
//CCLOG("hillsegment---%d,pointx---%f,pointy---%f,offset--%f",i,point1.x,point1.y,offsetX);
}
void Terrain::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
Node::draw(renderer, transform, flags);
_renderCmds[0].init(0.0f);
_renderCmds[0].func = CC_CALLBACK_0(Terrain::onDraw, this, transform);
renderer->addCommand(&_renderCmds[0]);
}
void Terrain::onDraw(const Mat4 &transform) {
auto glProgram = getGLProgram();
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
GL::bindTexture2D( terrainBottomTexId );
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, hillBottomVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, hillBottomTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)MAX_COORDINATES);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GL::bindTexture2D(terraintopTexId );
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, hillTopVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, hillTopTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)MAX_COORDINATES);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}