I am rendering H264 video frames from an IP camera which are decoded into BGRA32 pixel format via DirectX 11 and SharpDx in WPF via D3DImage control.
After lot of research and looking at various samples and examples I have managed to get it finally got it to render H264 frames with DirectX 11
My current setup involves setting setting up vertex shader and pixel shader as below:
var device = this.Device;
var context = device.ImmediateContext;
// Compile Vertex and Pixel shaders
vertexShaderByteCode = ShaderBytecode.CompileFromFile("TriangleShader.fx", "VSMain", "vs_5_0", ShaderFlags.Debug, EffectFlags.None);
vertexShader = new VertexShader(device, vertexShaderByteCode);
pixelShaderByteCode = ShaderBytecode.CompileFromFile("TriangleShader.fx", "PSMain", "ps_5_0", ShaderFlags.Debug, EffectFlags.None);
pixelShader = new PixelShader(device, pixelShaderByteCode);
// Layout from VertexShader input signature
// An input layout is the layout of the data containing the location and properties of a vertex. It would be a format of data that you can modify and set according
layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] {
new InputElement("SV_Position", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("COLOR", 0, Format.R32G32_Float, 16, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0),
});
// Write vertex data to a datastream
var stream = new DataStream(Utilities.SizeOf<Vertex>() * 6, true, true);
int iWidth = (int)this.ActualWidth;
int iHeight = (int)this.ActualHeight;
float top = iWidth / 2;
float bottom = iHeight / 2;
stream.WriteRange(new[]
{
new Vertex(
new Vector4(-top, bottom, 0.5f, 0.0f), // position top-center
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-center (r,g,b,alpha)
new Vector2(0f,0f)),
new Vertex(
new Vector4(top, bottom, 0.5f, 0.0f), // position top-right
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-right (r,g,b,alpha)
new Vector2(iWidth,iHeight)),
new Vertex(
new Vector4(-top, -bottom, 0.5f, 0.0f), // position bottom-left
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-left (r,g,b,alpha)
new Vector2(iWidth,iHeight)),
new Vertex(
new Vector4(-top, -bottom, 0.5f, 0.0f), // position bottom-right
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-left (r,g,b,alpha)
new Vector2(iWidth,0f)),
new Vertex(
new Vector4(top, -bottom, 0.5f, 0.0f), // position bottom-right
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-right (r,g,b,alpha)
new Vector2(iWidth,iHeight)),
new Vertex(
new Vector4(top, bottom, 0.5f, 0.0f), // position top-right
new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-right (r,g,b,alpha)
new Vector2(0f, iHeight)),
});
stream.Position = 0;
// Instantiate Vertex buiffer from vertex data
//
vertices = new SharpDX.Direct3D11.Buffer(device, stream, new BufferDescription()
{
BindFlags = BindFlags.VertexBuffer,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None,
SizeInBytes = Utilities.SizeOf<Vertex>() * 6,
Usage = ResourceUsage.Default,
StructureByteStride = 0
});
stream.Dispose();
// Prepare All the stages
context.InputAssembler.InputLayout = (layout);
context.InputAssembler.PrimitiveTopology = (PrimitiveTopology.TriangleStrip);
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vertex>(), 0));
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
context.OutputMerger.SetTargets(m_RenderTargetView);
When ever i receive a new frame then I update the RenderTexture by mapping the resource as below:
device.ImmediateContext.ClearRenderTargetView(this.m_RenderTargetView, Color4.Black);
Texture2DDescription colordesc = new Texture2DDescription
{
BindFlags = BindFlags.ShaderResource,
Format = m_PixelFormat,
Width = iWidth,
Height = iHeight,
MipLevels = 1,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Dynamic,
OptionFlags = ResourceOptionFlags.None,
CpuAccessFlags = CpuAccessFlags.Write,
ArraySize = 1
};
Texture2D newFrameTexture = new Texture2D(this.Device, colordesc);
DataStream dtStream = null;
DataBox dBox = Device.ImmediateContext.MapSubresource(newFrameTexture, 0, MapMode.WriteDiscard, 0, out dtStream);
if (dtStream != null)
{
int iRowPitch = dBox.RowPitch;
for (int iHeightIndex = 0; iHeightIndex < iHeight; iHeightIndex++)
{
//Copy the image bytes to Texture
// we write row strides multiplies by bytes per pixel
// as our case is bgra32 which is 4 bytes
dtStream.Position = iHeightIndex * iRowPitch;
Marshal.Copy(decodedData, iHeightIndex * iWidth * 4, new IntPtr(dtStream.DataPointer.ToInt64() + iHeightIndex * iRowPitch), iWidth * 4);
}
}
Device.ImmediateContext.UnmapSubresource(newFrameTexture, 0);
Texture2D srcTexture = m_RenderTargetView.ResourceAs<Texture2D>();
Device.ImmediateContext.CopySubresourceRegion(newFrameTexture, 0, null, this.RenderTarget, 0);
Device.ImmediateContext.Draw(6, 0);
Device.ImmediateContext.Flush();
this.D3DSurface.InvalidateD3DImage();
Disposer.SafeDispose(ref newFrameTexture);
My Effects/HLSL file:
Texture2D ShaderTexture : register(t0);
SamplerState Sampler : register(s0);
cbuffer PerObject: register(b0)
{
float4x4 WorldViewProj;
};
struct VertexShaderInput
{
float4 Position : SV_Position;
float4 Color : COLOR;
float2 TextureUV : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : SV_Position;
float4 Color : COLOR;
float2 TextureUV : TEXCOORD0;
};
VertexShaderOutput VSMain(VertexShaderInput input)
{
VertexShaderOutput output = (VertexShaderOutput)0;
output.Position = mul(input.Position, WorldViewProj);
output.Color = mul(input.Color, WorldViewProj);
output.TextureUV = input.TextureUV;
return output;
}
float4 PSMain(VertexShaderOutput input) : SV_Target
{
return ShaderTexture.Sample(Sampler, input.TextureUV).rgb;
}
Images are rendered correctly but it seem they are opaque if the background color of the parent color is anything other than black.
Now i can't seem to figure out what exactly is going on here which is rendering my texture as transparent.
I have also tried to render when the parent grid control has its background as a picture of a koala as shown below:
Any help in this matter would be much appreciated.
Related
arrayOfPaint[i] = new GradientPaint(0.0F, 0.0F, Color.green, 0.0F, 0.0F, Color.green);
// arrayOfPaint[i] = new GradientPaint(0.0F, 0.0F, Color.red, 0.0F, 0.0F, Color.red);
}
}
}
/* arrayOfPaint[0] = new GradientPaint(0.0F, 0.0F, Color.red, 0.0F, 0.0F, Color.red);
arrayOfPaint[1] = new GradientPaint(0.0F, 0.0F, Color.green, 0.0F, 0.0F, Color.green);
arrayOfPaint[2] = new GradientPaint(0.0F, 0.0F, Color.blue, 0.0F, 0.0F, Color.blue); */
CategoryDataset paramCategoryDatasetCylinder = localDefaultCategoryDatasetCylinder;
JFreeChart localJFreeChartCylinder = ChartFactory.createBarChart3D("", "Section", "Percentage", paramCategoryDatasetCylinder ,PlotOrientation.HORIZONTAL, true, true, false);
CategoryPlot localCategoryPlotCylinder = (CategoryPlot)localJFreeChartCylinder.getPlot();
/* if(compCode.equalsIgnoreCase("0094000") && domainName.equalsIgnoreCase("L and T")){
CategoryAxis yAxis = (CategoryAxis)localCategoryPlotCylinder.getDomainAxis();
yAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
} */
localCategoryPlotCylinder.setBackgroundPaint(Color.white);
localCategoryPlotCylinder.setRangeGridlinesVisible(true);
localCategoryPlotCylinder.setRangeGridlinePaint(Color.BLACK);
localJFreeChartCylinder.setBackgroundPaint(new GradientPaint(0.0F, 0.0F, Color.white, 350.0F, 0.0F, Color.white, true));
I have set GREEN color for both of the bars but I am getting difference in color. I am unable to figure out why it is happpening. Please help in this regard
I am making a solar system simulator in Processing. I have initialsed an array in the Planet class which holdes the textures for the PShape planetary objects.
I have added this array to the constructor. Then I tried to call it in the main class where I have initialised the planets, but I get the following erros:
Main class: Syntax Error - Error on parametre or method declaration near 'void'?
Clearly I am missing something or done something wrong. Thank you for the reply.
// Solar_system_enginee main class
//Solar system and it's gravitation's simulation.
// The central sun applies gravitation to other celestial bodies
PImage background;
PImage sun_Texture;
float cameraX, cameraY;
// zoom and pan
float scale = 0.06;
float xPan = 600;
float yPan = 398;
boolean zoomIn = false;
boolean zoomOut = false;
//includes
Sun sun;
Planet mercury;
Planet venus;
Planet earth;
Planet mars;
Planet jupiter;
Planet saturn;
Planet uranus;
Planet neptune;
Planet pluto;
Planet _planetTextures
//screen setup
void setup() {
//Screen size
size(1200, 799, P3D);
sun_Texture = loadImage("sun.jpg");
// Celestial object properties
// 1; Planet's size
// 2; Planet's color / texture
// 3; Movement speed
// 4; Planet's path color
// 5; Planet's path size
// 6; Distance from Sun
// 7; Planet's number of moons // need to check it
//Spawn celestial objects
sun = new Sun(696, color(255, 50, 0));
mercury = new Planet(5, 0.2, 2, color(255, 200, 100), 1448, _planetTextures[0]);
venus = new Planet(12, 0.2, 2, color(150, 10, 100), 1499, _planetTextures[1]);
earth = new Planet(13, 0.2, 2, color(255, 255, 100, 100), 1540, _planetTextures[2]);
//mars = new Planet(7, 0.5, 2, color(167, 45, 160), 1618);
//jupiter = new Planet(143, 0.5, 2, color(167, 45, 160), 2169);
//saturn = new Planet(121, 0.5, 2, color(167, 45, 160), 2825);
//uranus = new Planet(51, 0.5, 2, color(167, 45, 160), 4263);
//neptune = new Planet(50,0.5, 2, color(167, 45, 160), 5886);
//pluto = new Planet(2, 0.5, 2, color(167, 45, 160), 6486);
}
// sceene setup
void sceene() {
// Load background image
background = loadImage("stars.jpg");
background(background);
// Set it in the middle of the screen
translate(width/2, height/2, 0);
}
// draw setup
void draw() {
// Zoom towards the center of the screen, rather the edge of the screen
translate(width/2, height/2, 0);
scale(scale);
// Translate Y and X pan
translate( -xPan, -yPan);
// Draw background
sceene();
// Zoom In
if (zoomIn) {
scale *= 1.01;
}
// Zoom Out
if (zoomOut) {
scale /= 1.01;
}
// Display sun and rotate Y axis camera around sun
sun.display();
sun.move(mouseY);
//mercury
mercury.display();
mercury.move();
//venus
venus.display();
venus.move();
//earth
earth.display();
earth.move();
////mars
//mars.display();
//mars.move();
////jupiter
//jupiter.display();
//jupiter.move();
////saturn
//saturn.display();
//saturn.move();
////uranus
//uranus.display();
//uranus.move();
////neptune
//neptune.display();
//neptune.move();
////pluto
//pluto.display();
//pluto.move();
}
// Key press record function, responsible for zoom in and out of scene
void keyPressed() {
if (keyCode == UP) {
zoomIn = true;
zoomOut = false;
}
if (keyCode == DOWN) {
zoomIn = false;
zoomOut = true;
}
}
void keyReleased() {
if (keyCode == UP) {
zoomIn = false;
}
if (keyCode == DOWN) {
zoomOut = false;
}
}
// Planets class
class Planet {
float radius = 0;
float moveSpeed;
float distance;
float size;
color planetColor;
int pathSize;
color pathColor;
PShape planet;
PImage[] planetTextures = new PImage [3];
Moon moon;
Planet(int _size, float _speed, int _path_size, color _path_color, float _dist, PImage[] _planetTextures) { //color _color
size = _size;
//planetColor = _color;
moveSpeed = _speed;
pathColor = _path_color;
pathSize = _path_size;
distance = _dist;
planetTextures = _planetTextures;
moon = new Moon(10, color(200, 200, 100));
// Set planet's texture
noStroke();
noFill();
planet = createShape(SPHERE, size);
planet.setTexture(_planetTextures[0]);
// Load textures into an array
planetTextures[0] = loadImage ("mercury.jpg");
planetTextures[1] = loadImage ("venus.jpg");
planetTextures[2] = loadImage ("earth.jpg");
}
void display() {
pushMatrix();
//path
stroke(pathColor);
strokeWeight(2);
noFill();
rotateY(radius * moveSpeed);
rotateX(PI/2);
ellipse(0, 0, 2*distance, 2*distance);
//body
noStroke();
fill(planetColor);
translate(distance, 0, 0);
shape(planet);
//sphere(size);
moon.display();
moon.move();
popMatrix();
}
void move() {
radius += moveSpeed;
}
}
The Syntax Error - Missing name or ; near ‘void’? error occurs between Planet _planetTextures and void setup().
Sometimes error can be a bit cryptic: in this case it's as straightforward as it can be: you forgot to add ; at the end of Planet _planetTextures.
That being said, I've spotted a bunch of other areas in your code you might want to revise:
_planetTextures is later used as if it's a PImage[] in setup() when you instantiate planets
the Planet constructor takes in a PImage[] _planetTextures argument. If a single planet uses a single texture, maybe you meant PImage _planetTexture instead ?
The Planet constructor loads 3 images (mercury, venus, earth): should it be task of the main sketch to load all assets, then pass each single PImage to it's respective planet (instead of reloading the same 3 images for every single planet instance)
since the planet texture is only once in the constructor, there's no need for the PImage[] property
the backround PImage was loaded continously, multiple times per frame in sceene() (called from draw()): you might want to load the image once in setup.
Here is your code with the above tweaks applied:
//Solar system and it's gravitation's simulation.
// The central sun applies gravitation to other celestial bodies
PImage background;
PImage sun_Texture;
float cameraX, cameraY;
// zoom and pan
float scale = 0.06;
float xPan = 600;
float yPan = 398;
boolean zoomIn = false;
boolean zoomOut = false;
//includes
Sun sun;
Planet mercury;
Planet venus;
Planet earth;
Planet mars;
Planet jupiter;
Planet saturn;
Planet uranus;
Planet neptune;
Planet pluto;
PImage[] planetTextures;
//screen setup
void setup() {
//Screen size
size(1200, 799, P3D);
sun_Texture = loadImage("sun.jpg");
// Celestial object properties
// 1; Planet's size
// 2; Planet's color / texture
// 3; Movement speed
// 4; Planet's path color
// 5; Planet's path size
// 6; Distance from Sun
// 7; Planet's number of moons // need to check it
// Load background image
background = loadImage("stars.jpg");
// Load textures into an array
planetTextures[0] = loadImage ("mercury.jpg");
planetTextures[1] = loadImage ("venus.jpg");
planetTextures[2] = loadImage ("earth.jpg");
//Spawn celestial objects
sun = new Sun(696, color(255, 50, 0));
mercury = new Planet(5, 0.2, 2, color(255, 200, 100), 1448, planetTextures[0]);
venus = new Planet(12, 0.2, 2, color(150, 10, 100), 1499, planetTextures[1]);
earth = new Planet(13, 0.2, 2, color(255, 255, 100, 100), 1540, planetTextures[2]);
//mars = new Planet(7, 0.5, 2, color(167, 45, 160), 1618);
//jupiter = new Planet(143, 0.5, 2, color(167, 45, 160), 2169);
//saturn = new Planet(121, 0.5, 2, color(167, 45, 160), 2825);
//uranus = new Planet(51, 0.5, 2, color(167, 45, 160), 4263);
//neptune = new Planet(50,0.5, 2, color(167, 45, 160), 5886);
//pluto = new Planet(2, 0.5, 2, color(167, 45, 160), 6486);
}
// sceene setup
void scene() {
background(background);
// Set it in the middle of the screen
translate(width/2, height/2, 0);
}
// draw setup
void draw() {
// Zoom towards the center of the screen, rather the edge of the screen
translate(width/2, height/2, 0);
scale(scale);
// Translate Y and X pan
translate( -xPan, -yPan);
// Draw background
scene();
// Zoom In
if (zoomIn) {
scale *= 1.01;
}
// Zoom Out
if (zoomOut) {
scale /= 1.01;
}
// Display sun and rotate Y axis camera around sun
sun.display();
sun.move(mouseY);
//mercury
mercury.display();
mercury.move();
//venus
venus.display();
venus.move();
//earth
earth.display();
earth.move();
////mars
//mars.display();
//mars.move();
////jupiter
//jupiter.display();
//jupiter.move();
////saturn
//saturn.display();
//saturn.move();
////uranus
//uranus.display();
//uranus.move();
////neptune
//neptune.display();
//neptune.move();
////pluto
//pluto.display();
//pluto.move();
}
// Key press record function, responsible for zoom in and out of scene
void keyPressed() {
if (keyCode == UP) {
zoomIn = true;
zoomOut = false;
}
if (keyCode == DOWN) {
zoomIn = false;
zoomOut = true;
}
}
void keyReleased() {
if (keyCode == UP) {
zoomIn = false;
}
if (keyCode == DOWN) {
zoomOut = false;
}
}
class Planet {
float radius = 0;
float moveSpeed;
float distance;
float size;
color planetColor;
int pathSize;
color pathColor;
PShape planet;
Moon moon;
Planet(int _size, float _speed, int _path_size, color _path_color, float _dist, PImage _planetTexture) { //color _color
size = _size;
//planetColor = _color;
moveSpeed = _speed;
pathColor = _path_color;
pathSize = _path_size;
distance = _dist;
moon = new Moon(10, color(200, 200, 100));
// Set planet's texture
noStroke();
noFill();
planet = createShape(SPHERE, size);
planet.setTexture(_planetTexture);
}
void display() {
pushMatrix();
//path
stroke(pathColor);
strokeWeight(2);
noFill();
rotateY(radius * moveSpeed);
rotateX(PI/2);
ellipse(0, 0, 2*distance, 2*distance);
//body
noStroke();
fill(planetColor);
translate(distance, 0, 0);
shape(planet);
//sphere(size);
moon.display();
moon.move();
popMatrix();
}
void move() {
radius += moveSpeed;
}
}
It would've made it easier to for others to test if you would have also posted the Sun/Moon classes and the textures uses: something to remember for future posts. (The easier it is for others to replicate your issue the more like to get (good) answers).
Not bad progress and you're getting the main points about classes.
There might still be confusion over how arguments get passed from the sketch(global) scope to instances, but that may also be an artefact of perhaps trying to write a lot of code in one go ?
If that's the case, I recommend slowing down, writing one bit of functionality at a time (e.g. one function or class method at a time, running the sketch and testing to ensure it works as expected first). Once a bit of code works as expected to you can move to the next and ideally text combinations of the newly added functionalities to ensure that there no weird interactions between classes. Constantly testing how the code behaves may appear slower, but resting assured the code works as go along is faster on the long run and it definitely makes debugging much easier (likely to be most recently added functionality which is also freshes in your memory). Have fun coding !
I’m trying to add freetype text to my running program. The code below was adapted from EdoardoLuciani. No text is shown, though.
I checked if the the tff file is loaded correctly and that valid textures ids are generated. They are o.k.
The remaining of the program is running without problem, but no text is drawn.
Could you help me to find what's wrong, please?
Environment:
DELL XPS
GPU 1050
OpenGL 4.6
Win32
Language C
// Main program
...
initText()
...
// Drawing loop
...
{
drawText(10, 300, "Hello World!");
}
void initText()
{
// Extract glyphs textures
//
glUseProgram(textShader);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, "arial.ttf", 0, &face);
FT_Set_Pixel_Sizes(face, 0, 48);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int c = 0; c < 128; c++)
{
FT_Load_Char(face, c, FT_LOAD_RENDER);
//
// Extract glyph
//
GLuint texture;
glCreateTextures(GL_TEXTURE_2D,1, &texture);
glTextureStorage2D(texture, 1, GL_R8, face->glyph->bitmap.width, face->glyph->bitmap.rows);
glTextureSubImage2D(texture, 0, 0, 0, face->glyph->bitmap.width, face->glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glBindTexture(GL_TEXTURE_2D, texture);
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);
glBindTexture(GL_TEXTURE_2D, 0);
//
// Save glyph to lookup table
//
Character ch;
ch.texture = texture;
ch.bearing[0] = face->glyph->bitmap.width;
ch.bearing[1] = face->glyph->bitmap.rows;
ch.size[0] = face->glyph->bitmap_left;
ch.size[1] = face->glyph->bitmap_top;
ch.advance = face->glyph->advance.x;
characters[c] = ch;
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
//
// Create VAO
//
glCreateVertexArrays(1, &textVAO);
glBindVertexArray(textVAO);
//
// Create the unique VBO
//
glCreateBuffers(1, &VBO);
glNamedBufferStorage(VBO, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayVertexBuffer(textVAO, 0, VBO, 0, sizeof(GLfloat) * 4);
glVertexArrayAttribFormat(textVAO, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(textVAO, 0, 0);
glEnableVertexArrayAttrib(textVAO, 0);
//
// Send color to fragment shader
//
glUniform3f(6, 0.88f, 0.59f, 0.07f);
}
void drawText(float x, float y, float scale, char *text)
{
glEnable(GL_CULL_FACE);
glUseProgram(textShader);
glBindVertexArray(textVAO);
//
// Draw each character
//
char *c = text;
while(*c != 0)
{
Character ch = characters[(int)*c];
if(ch.bearing[0] != 0 && ch.bearing[1] != 0)
{
GLfloat xpos = x + ch.bearing[0] * scale;
GLfloat ypos = y - (ch.size[1] - ch.bearing[1]) * scale;
//
GLfloat w = ch.size[0] * scale;
GLfloat h = ch.size[1] * scale;
//
// Update VBO for each character
//
GLfloat vertices[6*4] =
{
xpos, ypos + h, 0.0f, 0.0f ,
xpos, ypos, 0.0f, 1.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos, ypos + h, 0.0f, 0.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos + w, ypos + h, 1.0f, 0.0f
};
glNamedBufferSubData(VBO, 0, sizeof(GLfloat)*6*4, vertices);
glBindTexture(GL_TEXTURE_2D, ch.texture);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
x += (ch.advance >> 6) * scale;
c++;
}
glDisable(GL_CULL_FACE);
}
The vertex shader:
#version 460 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
layout (location = 1) uniform mat4 projection;
out vec2 TexCoords;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}
The fragment shader:
#version 460 core
in vec2 TexCoords;
out vec4 color;
layout (binding = 0) uniform sampler2D text;
layout (location = 6) uniform vec3 textColor;
void main()
{
color = vec4(textColor, 1.0) * texture(text, TexCoords).r;
}
I hope to create an offScreen FBO, and use glReadPixels() to get the value of RGBA in this offScreen FBO. unfortunately, I got the error: GL_ERROR:0x0502
#import "ViewController.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#interface ViewController ()
{
GLuint backFBO;
GLuint defaultFBO;
int fbo_width;
int fbo_height;
//
GLuint _vertexArray;
GLuint _vertexBuffer;
GLuint _texCoordBuffer;
GLuint depthBuffer;
//
GLKMatrix4 _modelViewProjectionMatrix;
GLKMatrix3 _normalMatrix;
float _rotation;
}
#property (nonatomic, strong) GLKBaseEffect *baseEffect;
#property (nonatomic, strong) EAGLContext *context;
- (void)setupGL;
- (void)tearDownGL;
- (void)setupFBO;
#end
the vertex data and normal data of object in onScreen FBO
GLfloat gVertexData[] =
{
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f
};
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//1. setup context
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
];
if (!self.context) {
NSLog(#"Failed to create GLES Context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[self setupGL];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[self tearDownGL];
if ([EAGLContext currentContext] == self.context) {
[EAGLContext setCurrentContext:nil];
}
self.context = nil;
}
- (void) setupGL
{
[EAGLContext setCurrentContext:self.context];
self.baseEffect = [[GLKBaseEffect alloc] init];
glEnable(GL_DEPTH_TEST);
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gVertexData), gVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayOES(0);
// initialize FBO
[self setupFBO];
}
- (void) tearDownGL
{
[EAGLContext setCurrentContext:self.context];
glDeleteBuffers(1, &_vertexBuffer);
}
- (void)update
{
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
self.baseEffect.transform.projectionMatrix = projectionMatrix;
// Compute the model view matrix for the object rendered with ES2
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -2.0f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
self.baseEffect.transform.modelviewMatrix = modelViewMatrix;
_rotation += self.timeSinceLastUpdate * 0.5f;
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// render FBO tex
[self renderFBO];
// reset to main framebuffer
[((GLKView *) self.view) bindDrawable];
glViewport(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
// render main
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
#pragma mark - FBO
// intialize FBO
- (void)setupFBO
{
fbo_width = 512;
fbo_height = 512;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
NSLog(#"default FBO: %d", defaultFBO);
glGenFramebuffers(1, &backFBO);
glGenRenderbuffers(1, &depthBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbo_width, fbo_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
// FBO status check
GLenum status;
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
NSLog(#"fbo complete");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
NSLog(#"fbo unsupported");
break;
default:
/* programming error; will fail on all hardware */
NSLog(#"Framebuffer Error");
break;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
}
// render FBO
- (void)renderFBO
{
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
glViewport(0,0, fbo_width, fbo_height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
**//in here, I hope to get the value of RGBA in offScreen FBO**
Byte pixelColor[4] = {0,};
glReadPixels(50, 50, fbo_width, fbo_height, GL_RGBA, GL_UNSIGNED_BYTE, pixelColor);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
}
when I comment glReadPixels(), it's works well. Any help or advice would be much appreciated.
in your offScreen FBO, you should bind a GL_RENDERBUFFER, so you should add below code:
//create a new FBO
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
// add
GLuint _colorBuffer;
glGenRenderbuffers(1, &_colorBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, fbo_width , fbo_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER, _colorBuffer);
I hope this will fix your error. good luck !!!
I'm trying to display simple white cube in OpenGL with SDL. I've setup my VBO and IBO like this:
GLfloat vertexData[] =
{
-0.5f, -0.5f, -0.5f, // bot, left, back
-0.5f, 0.5f, -0.5f, // top, left, back
-0.5f, -0.5f, 0.5f, // bot, left, front
-0.5f, 0.5f, 0.5f, // top, left, front
0.5f, -0.5f, -0.5f, // bot, right, back
0.5f, -0.5f, 0.5f, // bot, right, front
0.5f, 0.5f, -0.5f, // top, right, back
0.5f, 0.5f, 0.5f // top, right, front
};
GLint indexData[] =
{
//back
0, 1, 6,
0, 5, 6,
//left
0, 2, 3,
0, 1, 3,
//right
4, 5, 7,
4, 6, 7,
//bot
0, 4, 5,
0, 2, 5,
//top
1, 3, 7,
1, 6, 7,
//front
2, 3, 7,
2, 5, 7
};
However, it looks like this:
What am I doing wrong?
Edit:
My init functions
bool App::OpenGLInit()
{
programID = glCreateProgram();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
std::string vertexString = getShaderFromFile("src/shader.vert");
const GLchar * vertexShaderSource = vertexString.c_str();
glShaderSource(vertexShader, 1, (const GLchar **)&vertexShaderSource, NULL);
glCompileShader(vertexShader);
glAttachShader(programID, vertexShader);
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
//Get fragment source
std::string fragmentString = getShaderFromFile("src/shader.frag");
const GLchar* fragmentShaderSource = fragmentString.c_str();
//Set fragment source
glShaderSource( fragmentShader, 1, (const GLchar **)&fragmentShaderSource, NULL );
//Compile fragment source
glCompileShader( fragmentShader );
glAttachShader(programID, fragmentShader );
glLinkProgram(programID);
return true;
}
bool App::OnInit()
{
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
if((screen = SDL_CreateWindow("Color Wars", 100, 100, 1024, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)) == NULL) {
return false;
}
if ((gl_context = SDL_GL_CreateContext(screen)) == NULL)
{
return false;
}
if((renderer = SDL_CreateRenderer(screen, -1, 0)) == NULL)
{
return false;
}
if (SDL_GL_SetSwapInterval(1) < 0)
return false;
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
return false;
}
if (!OpenGLInit())
return false;
game_screen = new GameScreen();
game_screen->Init(programID);
return true;
}
my Render functions:
void App::OnRender()
{
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( programID );
game_screen->Render(renderer);
glUseProgram( NULL );
SDL_GL_SwapWindow(screen);
}
void GameScreen::Render(SDL_Renderer *renderer)
{
//Enable vertex position
glEnableVertexAttribArray(vertex2DPosition);
//Set vertex data
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glVertexAttribPointer(vertex2DPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL );
//Set index data and render
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IBO );
glDrawElements(GL_TRIANGLE_FAN, 12, GL_UNSIGNED_INT, NULL );
//Disable vertex position
glDisableVertexAttribArray( vertex2DPosition );
}
Dummy text: asdasdasdasdasdasd
You have three things working against you in this example:
You are drawing a cube in Normalized Device Coordinates, which have the range XYZ: [-1,1].
You are drawing into a window that is not square, so the cube face is stretched because your coordinate space has nothing to do with the size of your window.
It appears to be a rectangle because you have not defined any viewing transformation and are viewing it face-on with no perspective.
You can correct all of this if you do this whenever your window is resized:
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho ((-1.0f * aspect), (1.0f * aspect), -1.0f, 1.0f, -1.0f, 1.0f);
glViewport (0, 0, width, height);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glRotatef (45.0f, 0.25f, 0.5f, 0.75f); // Let's rotate this sucker!
Where width and height are the width and height of your SDL window, respectively.
UPDATE:
See, now it is clear why this did not work. You never mentioned in your question that you were using shaders. Thank you for posting your updated code. In order for this to work with shaders you need to pass a projection and modelview matrix. You can use the same setup to build your matrices as I described using the old OpenGL matrix manipulation functions, and glm would probably make this easiest.