openGL es 2.0 TextureCoordinates parameter ios - c++

I have to crop a video.
So i modify the TextureCoordinates.
The code is as below.
const GLfloat squareTextureCoordinates[] = {
0.22f , 1.0f,
0.22f, 0.0f,
0.78f, 1.0f,
0.78f, 0.0f,
};
glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, 0, 0, squareVertices);
glVertexAttribPointer(inputTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, squareTextureCoordinates);
This code is work.
However,i need to support many size of iphone .(example:iphone6 have different size to iphone5)
So i use variable rather than const in TextureCoordinates.
And the new code is as below;
const float cropX=(float)(SCREEN_HEIGHT-SCREEN_WIDTH)/(float)(SCREEN_HEIGHT*2);
const float cropXR=1- (float)(SCREEN_HEIGHT-SCREEN_WIDTH)/(float)(SCREEN_HEIGHT*2);
const GLfloat squareTextureCoordinates[] = {
cropX , 1.0f,
cropX, 0.0f,
cropXR, 1.0f,
cropXR, 0.0f,
};
glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, 0, 0, squareVertices);
glVertexAttribPointer(inputTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, squareTextureCoordinates);
However, it doesn't work.
The screen is display nothing.
i cant figure out why i can't use const variable for TextureCoordinates.

I think you could test the second part of your code by changing the const values to the constants you used in the first part:
const float cropX = 0.22f;
const float cropXR = 0.78f;
const GLfloat squareTextureCoordinates[] = {
cropX , 1.0f,
cropX, 0.0f,
cropXR, 1.0f,
cropXR, 0.0f,
};
glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, 0, 0, squareVertices);
glVertexAttribPointer(inputTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, squareTextureCoordinates);
If this works (it should), you will see you can use const variables as a texture coordinate. However, I reckon the wrong part of the code is this:
const float cropX=(float)(SCREEN_HEIGHT-SCREEN_WIDTH)/(float)(SCREEN_HEIGHT*2);
const float cropXR=1- (float)(SCREEN_HEIGHT-SCREEN_WIDTH)/(float)(SCREEN_HEIGHT*2);
In texture coordinates, correct values are between 0 and 1. If width is bigger than height, this code won't work. In the specific case of an iPhone 5 and 6, which have the same proportion, same texture coordinates should work if the view that renders OpenGL code was resized (if you use autolayout for that view, you will probably solve the problem automatically).

Related

Why is my Index Generation Function not correctly building the triangle primitives?

I am trying to code a function which automatically populates a mesh's index vector container. The function should work without issue in theory as it generates the proper indices in their correct order; however, the triangles do not form! Instead, I am left with a single line.
My mesh generation code is supposed to build an octahedron and then render it in the main game loop. The mesh class is shown below in its entirety:
struct vertex
{
glm::vec3 position;
glm::vec3 color;
};
class Mesh
{
public:
GLuint VAO, VBO, EBO;
std::vector <vertex> vtx;
std::vector <glm::vec3> idx;
glm::mat4 modelMatrix = glm::mat4(1.f);
Mesh(glm::vec3 position, glm::vec3 scale)
{
vertexGen(6);
idx = indexGen(6);
modelMatrix = glm::scale(glm::translate(modelMatrix, position), scale);
initMesh();
};
void Render(Shader shaderProgram, Camera camera, bool wireframe)
{
glUseProgram(shaderProgram.ID);
glPatchParameteri(GL_PATCH_VERTICES, 3); // Indicates to the VAO that each group of three vertices is one patch (triangles)
glProgramUniformMatrix4fv(shaderProgram.ID, 0, 1, GL_FALSE, glm::value_ptr(modelMatrix));
glProgramUniformMatrix4fv(shaderProgram.ID, 1, 1, GL_FALSE, glm::value_ptr(camera.camMatrix));
glProgramUniform3fv(shaderProgram.ID, 2, 1, glm::value_ptr(camera.Position));
glBindVertexArray(VAO); // Binds the VAO to the shader program
if (wireframe)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_CULL_FACE);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//glEnable(GL_CULL_FACE);
}
glDrawElements(GL_PATCHES, idx.size(), GL_UNSIGNED_INT, 0); // Tells the shader program how to draw the primitives
}
private:
void vertexGen(int n) {
// Populate the base six vertices
vtx.push_back(vertex{ glm::vec3( 0.0f, 0.5f, 0.0f), glm::vec3(0.f, 1.f, 0.f) });
vtx.push_back(vertex{ glm::vec3(-0.5f, 0.0f, 0.0f), glm::vec3(0.f, 1.f, 0.f) });
vtx.push_back(vertex{ glm::vec3( 0.0f, 0.0f, -0.5f), glm::vec3(0.f, 1.f, 0.f) });
vtx.push_back(vertex{ glm::vec3( 0.5f, 0.0f, 0.0f), glm::vec3(0.f, 1.f, 0.f) });
vtx.push_back(vertex{ glm::vec3( 0.0f, 0.0f, 0.5f), glm::vec3(0.f, 1.f, 0.f) });
vtx.push_back(vertex{ glm::vec3( 0.0f,-0.5f, 0.0f), glm::vec3(0.f, 1.f, 0.f) });
}
std::vector<glm::vec3> indexGen(int n) {
std::vector<glm::vec3> indices;
// Calculate the indices for the top 4 triangles
indices.push_back(glm::vec3( 0, n - 5, n - 4 ));
indices.push_back(glm::vec3( 0, n - 4, n - 3 ));
indices.push_back(glm::vec3( 0, n - 3, n - 2 ));
indices.push_back(glm::vec3( 0, n - 2, n - 5 ));
// Calculate the indices for the bottom 4 triangles
indices.push_back(glm::vec3( 5, n - 5, n - 4));
indices.push_back(glm::vec3( 5, n - 4, n - 3));
indices.push_back(glm::vec3( 5, n - 3, n - 2));
indices.push_back(glm::vec3( 5, n - 2, n - 5));
return indices;
}
void initMesh()
{
glCreateVertexArrays(1, &VAO); // Sets the address of the uint VAO as the location of a gl vertex array object
glCreateBuffers(1, &VBO); // Sets the address of the uint VBO as the location of a gl buffer object
glCreateBuffers(1, &EBO); // Sets the address of the uint EBO as the location of a gl buffer object
glNamedBufferData(VBO, vtx.size() * sizeof(vtx[0]), vtx.data(), GL_STATIC_DRAW); // Sets the data of the buffer named VBO
glNamedBufferData(EBO, idx.size() * sizeof(idx[0]), idx.data(), GL_STATIC_DRAW); // Sets the data of the buffer named EBO
glEnableVertexArrayAttrib(VAO, 0); // Enables an attribute of the VAO in location 0
glEnableVertexArrayAttrib(VAO, 1); // Enables an attribute of the VAO in location 1
glVertexArrayAttribBinding(VAO, 0, 0); // Layout Location of Position Vectors
glVertexArrayAttribBinding(VAO, 1, 0); // Layout Location of Color Values
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); // Size, and Type of Position Vectors
glVertexArrayAttribFormat(VAO, 1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat)); // For the Color Values
glVertexArrayVertexBuffer(VAO, 0, VBO, 0, 6 * sizeof(GLfloat)); // Sets the VBO to indicate the start, offset, and stride of vertex data in the VAO
glVertexArrayElementBuffer(VAO, EBO); // Sets the EBO to index the VAO vertex connections
}
};
I took this problem step by step and did all of the basic math on paper. The index generation function returns the expected indices in their correct order as just having the indices written out, but it differs in that the written-out indices generate the desired result whereas the generation function only produces a single line when rendered:
I suspect that the issue lies in my mesh initialization function (initMesh), specifically in the glNamedBufferData or glVertexArrayVertexBuffer, but my knowledge of the functions is very limited. I tried changing the parameter of the glNamedBufferData function to different variations of idx.size()*sizeof(idx[0].x), but that yielded the same results, so I am at a loss. Could someone help me fix this, please?
glm::vec3 is a vector of floats (I think) but you are telling OpenGL to read them as unsigned ints.
Float 0.0 is 0x00000000 (i.e. same as int 0), but float 1.0 is 0x3f800000 (same as int 1065353216). They aren't compatible ways to store numbers. You could try glm::ivec3 which is a vector of ints, but I think most people would use std::vector<int> (or unsigned int) and use 3 entries per triangle.
I think it's okay in this case, but I don't like to use types like ivec3 when I mean to have 3 separate ints isn't always a good practice, because the compiler can insert padding in unexpected places. It's possible that on some platforms, ivec3 could be 3 ints and an extra 4 bytes of padding, making 16 bytes in total, and the extra padding bytes throw off the layout you're relying on. glDrawArrays wouldn't skip over padding after every 3 indices and there would be no way to tell it to do that. It's okay for vertices, since you can tell OpenGL exactly where the data is.

OpenGL Combining multiple cubes into a single mesh [duplicate]

This question already exists:
OpenGL Converting from busy vertex buffer to element buffer
Closed 6 months ago.
I am having trouble merging multiple simple objects into a single mesh with OpenGL.
Before I go on I am aware of instancing and I'm certain that it's not what I want.
I'm drawing a cube with the following buffers:
float cubeVertices[] = {
-0.5f, 0.5f, 0.5f, //front top left
0.5f, 0.5f, 0.5f, //front top right
-0.5f, -0.5f, 0.5f, //front bottom left
0.5f, -0.5f, 0.5f, //front bottom right
-0.5f, 0.5f, -0.5f, //back top left
0.5f, 0.5f, -0.5f, //back top right
-0.5f, -0.5f, -0.5f, //back bottom left
0.5f, -0.5f, -0.5f //back bottom right
};
unsigned int cubeIndices[] = {
0, 2, 1, //FRONT
1, 2, 3,
0, 1, 4, //TOP
4, 1, 5,
1, 3, 5, //RIGHT
5, 3, 7,
2, 7, 3, //BOTTOM
7, 2, 6,
6, 2, 0, //LEFT
0, 4, 6,
6, 4, 5, //BACK
5, 7, 6
};
I then call glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr) which works as wanted.
Now my problem is if I want to draw multiple cubes in the same draw call (Still don't want instancing).
My current way of rendering multiple cubes is by:
for (int y = 0; y < 2; ++y)
{
for (int x = 0; x < 2; ++x)
{
for (int z = 0; z < 2; ++z)
{
model = glm::mat4{1.0f};
model = glm::translate(model, glm::vec3{x, y, z});
shader.SetMat4("uModel", model);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
}
}
}
Which is fine for a 2x2x2 cube of cubes but if I want to go larger like 32x32x32 it starts to fall apart performance wise.
So I was wondering how I can merge this 2x2x2 cube into a single mesh and call glDrawElements(GL_TRIANGLES, 36 * 8, GL_UNSIGNED_INT, nullptr) or similar.
I've tried:
std::array<glm::vec3, 8> locations{};
for (int x = 0; x < 2; ++x)
{
for (int y = 0; y < 2; ++y)
{
for (int z = 0; z < 2; ++z)
{
locations[x + 2 * (y + 2 * z)] = glm::vec3{x, y, z};
}
}
}
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO[1]);
glBufferData(GL_ARRAY_BUFFER, locations.size(), locations.data(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
And using gl_Position = uProjection * uView * uModel * vec4(aPos * aLocation, 1.0f); where uModel is just a glm::mat4{1.0f}, aPos is from cubeVertices and aLocation is from the locations array.
I've got a couple ideas on why it doesn't work which I'll list.
First off: aLocation is different for every vertex instead of staying constant for the entire cube and then changing to the next location. Not sure how to do that. I could copy and paste the same location for every vertex I assume but that seems to defeat the purpose of using an element buffer in the first place.
Second: cubeIndices[] only holds enough indices for a single cube so I could also fix that by copy pasting the cubeIndices 8 times but doesn't that defeat the purpose of using an element buffer if I just have the same data 8 times?
So maybe a double element buffer could work?
I know instancing does seem like a really obvious solution but I guarantee that it's not what I am after.
I'm quite new to OpenGL so I don't have the most solid grasp of what I'm doing yet so I'm just trying to figure OpenGL out by making small projects. If someone could help it would be greatly appreciated.
It really looks like it is instancing that you want.
Do your objects moves but the geometry of each one stays the same? instancing.
Does each object move with bones animations? instancing.
Does the geometry moves every frame and not bone animated? not instancing, dynamic buffers.
One of the bottleneck of GPU is main memory=>GPU data transfers. You will struggle to update a lot of geometry at once because you need to transfer all the vertex every frame (~100 times a sec).
Your 2nd code is good. If you have performance issues its for another reason.
If you try to draw 32*32*32 cubes, that's 6*2*32*32*32=393 216 triangles. That could be a lot depending on your hardware.
If you used a big index buffer, everything would be the same, but you would use 6*3*2*32*32*32*sizeof(UINT)=4.7MB instead of 6*3*2*sizeof(UINT)=144B of memory space for your index buffer.
If the vertex positions are changing, you don't have to update the index buffer, there is probably a way to select a different start vertex. There is in Direct3D but IDK for opengl.

understanding OpenGL ES crash causes and ways to debug one

Leaning how to use OpenGL ES under cocos2d-x.
Help me to understand while the below function crashes with EXC_BAD_ACCESS on noise->visit(); which probably means that my OpenGL state is screwed-up by the time the command is executed.
My method:
Sprite* GameLevelLayer::spriteWithColor(Color4F bgColor, float textureWidth, float textureHeight)
{
// 1: Create new RenderTexture
auto rt = RenderTexture::create(textureWidth, textureHeight);
// 2: Call RenderTexture:begin
rt->beginWithClear(bgColor.r, bgColor.g, bgColor.b, bgColor.a);
// 3: Draw into the texture
//// gradient
gradient_command.init(rt->getGlobalZOrder());
gradient_command.func = std::bind(&GameLevelLayer::onDrawGradient, this, textureWidth, textureHeight);
auto renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&gradient_command);
//// noise cloud
BlendFunc blendFunc;
blendFunc.src = GL_DST_COLOR;
blendFunc.dst = GL_ZERO;
auto noise = Sprite::create("Noise.png");
noise->setBlendFunc(blendFunc);
noise->setPosition(Vec2(textureWidth / 2, textureHeight / 2));
// XXX
noise->visit();
// 4: Call RenderTexture:end
rt->end();
// 5: Create a new Sprite from the texture
return Sprite::createWithTexture(rt->getSprite()->getTexture());
}
and the gradient:
void GameLevelLayer::onDrawGradient(float textureWidth, float textureHeight)
{
setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
getGLProgram()->use();
getGLProgram()->setUniformsForBuiltins();
float gradientAlpha = 0.8f;
std::vector<Vec2> vertices;
std::vector<Color4F> colors;
vertices.push_back(Vec2(0, 0));
colors.push_back(Color4F(0.0f, 0.0f, 0.0f, 0.0f ));
vertices.push_back(Vec2(textureWidth, 0));
colors.push_back(Color4F(0.0f, 0.0f, 0.0f, 0.0f ));
vertices.push_back(Vec2(0, textureHeight));
colors.push_back(Color4F(0.0f, 0.0f, 0.0f, gradientAlpha ));
vertices.push_back(Vec2(textureWidth, textureHeight));
colors.push_back(Color4F(0.0f, 0.0f, 0.0f, gradientAlpha ));
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices.data());
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, colors.data());
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)vertices.size());
}
Is this because I am using parameters of a wrong size, somewhere? How does one go about debugging something like this?

DirectX 11 LINELIST_TOPOLOGY uncompleted 2D rectangle at left-top coordinates

I'm doing something with DirectX 11 and came to a rectagle drawing (empty, non-colored), seemed simple for me at start (linelist_topology, 8 indices) but when I have it on the screen I see that my rectangle is kinda incomleted at left-top coordinate, there is a point of a background color there, the code is not complicated at all, vertices are 2D space:
SIMPLEVERTEX gvFrameVertices[4]=
{XMFLOAT3(0.0f,0.0f,1.0f),XMFLOAT2(0.0f, 0.0f),
XMFLOAT3(1.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 0.0f),
XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT2(1.0f, 1.0f),
XMFLOAT3(0.0f, -1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f)};
indices:
WORD gvRectangularIndices[8] = { 0, 1, 1, 2, 2, 3, 3, 0 };
Shader just returns given color in constant buffer:
float4 PS_PANEL(PS_INPUT input) : SV_Target
{
return fontcolor;
}
Function code itself:
VOID rectangle(INT _left, INT _top, INT _width, INT _height, XMFLOAT4 _color)
{
XMMATRIX scale;
XMMATRIX translate;
XMMATRIX world;
scale = XMMatrixScaling( _width, _height, 1.0f );
translate = XMMatrixTranslation(_left, gvHeight - _top, 1.0f);
world = scale * translate;
gvConstantBufferData.world = XMMatrixTranspose(world);
gvConstantBufferData.index = 1.0f;
gvConstantBufferData.color = _color;
gvContext->PSSetShader(gvPanelPixelshader, NULL, 0);
gvContext->UpdateSubresource(gvConstantBuffer, 0, NULL, &gvConstantBufferData, 0, 0 );
gvContext->IASetIndexBuffer(gvLinelistIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
gvContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
gvContext->DrawIndexed(8, 0, 0);
gvContext->IASetIndexBuffer(gvTriangleslistIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
gvContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
};
gvHeight - _top - I'm using orthographic matrix for projection, so the coordinate center is at left-bottom, that why need to substract for proper Y coordinate.
gvOrthographicProjection = XMMatrixOrthographicOffCenterLH( 0.0f, gvWidth, 0.0f, gvHeight, 0.01f, 100.0f );
Do you have any idea what can cause this pointal incompletness of a rectangle in my case or I need to supply more code info (don't really want to link lines of the whole initializations cause they seem very obvious and simple for me, done for /at c++ and directx amateur level :)
Thank you:)

glDrawElements drawing all objects connected

I can't figure out how to get glDrawElements to not connect everything it draws...
//Draw Reds
glEnableVertexAttribArray(vLoc);
glEnableVertexAttribArray(cLoc);
glBindBuffer(GL_ARRAY_BUFFER,positionBufferRed);
glVertexAttribPointer(vLoc,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ARRAY_BUFFER,redBuffer);
glVertexAttribPointer(cLoc,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,elementBufferRed);
glDrawElements(GL_TRIANGLES,nElements*3,GL_UNSIGNED_INT,0);
glDisableVertexAttribArray(vLoc);
glDisableVertexAttribArray(cLoc);
//Draw Blues
glEnableVertexAttribArray(vLoc);
glEnableVertexAttribArray(cLoc);
glBindBuffer(GL_ARRAY_BUFFER,positionBufferBlue);
glVertexAttribPointer(vLoc,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ARRAY_BUFFER,blueBuffer);
glVertexAttribPointer(cLoc,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,elementBufferBlue);
glDrawElements(GL_TRIANGLES,nElements*3,GL_UNSIGNED_INT,0);
glDisableVertexAttribArray(vLoc);
glDisableVertexAttribArray(cLoc);
This is what the result looks like:
http://img338.imageshack.us/img338/2440/cows.png
Should be two separate cows but instead they're connected with black lines. Any advice will be appreciated!
My guess is that the number of elements you're trying to draw is wrong (too big). So the GPU tries to get triangles that don't exist in the buffer, and accidentally access the vertices of the next mesh, but not the color (black).
Try with glDrawElements(GL_TRIANGLES,nElements,GL_UNSIGNED_INT,0);
If it doesn't work, try with a handcoded single triangle.
Here's an example :
GLsizei const TonemapperElementCount = 3;
GLsizeiptr const TonemapperElementSize = TonemapperElementCount * sizeof(glm::uint32);
glm::uint32 const TonemapperElementData[TonemapperElementCount] =
{
0, 1, 2,
};
GLsizei const TonemapperVertexCount = 3;
GLsizeiptr const TonemapperPositionSize = TonemapperVertexCount * sizeof(glm::vec4);
glm::vec4 const TonemapperPositionData[TonemapperVertexCount] =
{ // A full-screen triangle in normalized screen space.
glm::vec4( -1.0f, -1.0f,0,1),
glm::vec4( 3.0f, -1.0f ,0,1),
glm::vec4( -1.0f, 3.0f ,0,1),
};