I'm trying to display an image on a GLView in react native.
I was inspired by this link to write my code https://webglfundamentals.org/webgl/lessons/webgl-2d-drawimage.html
I have this component who calls a GLContext2D class:
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Expo from 'expo';
import GLContext2D from '../../lib/GLContext2D';
export default class Scene extends Component {
constructor(props, context) {
super(props, context);
this.state = {
ready: false,
};
}
componentDidMount() {
(async () => {
this._textureAsset = Expo.Asset.fromModule(
require('../../test.jpg')
);
await this._textureAsset.downloadAsync();
console.log("ok");
this.setState({ ready: true });
})();
}
render () {
return this.state.ready
? <Expo.GLView
style={styles.view}
onContextCreate={this._onContextCreate}
/>
: <Expo.AppLoading />;
}
_onContextCreate = gl => {
console.log(this._textureAsset);
var ctx = new GLContext2D(gl);
var test = ctx.createTextureFromAsset(this._textureAsset);
ctx.clear();
gl.clearColor(0, 0, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
ctx.drawImage(test.texture, test.width, test.height, 0, 200);
gl.flush();
gl.endFrameEXP();
}
}
const styles = StyleSheet.create({
view: {
width: 500,
height: 1000,
backgroundColor: 'yellow'
}
});
And the GLContext2D class:
import Expo from 'expo';
import {mat4} from 'gl-matrix';
const vertSrc = `
attribute vec4 a_position;
attribute vec2 a_texcoord;
uniform mat4 u_matrix;
uniform mat4 u_textureMatrix;
varying vec2 v_texcoord;
void main() {
gl_Position = u_matrix * a_position;
v_texcoord = (u_textureMatrix * vec4(a_texcoord, 0, 1)).xy;
}
`;
const fragSrc = `
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
if (v_texcoord.x < 0.0 ||
v_texcoord.y < 0.0 ||
v_texcoord.x > 1.0 ||
v_texcoord.y > 1.0) {
gl_FragColor = vec4(1, 0, 1, 1); // blue
return;
}
gl_FragColor = texture2D(u_texture, v_texcoord);
}
`;
export default class GLContext2D {
constructor(gl) {
var vert;
var frag;
this._gl = gl;
vert = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vert, vertSrc);
gl.compileShader(vert);
frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frag, fragSrc);
gl.compileShader(frag);
this._program = gl.createProgram();
gl.attachShader(this._program, vert);
gl.attachShader(this._program, frag);
gl.linkProgram(this._program);
this._locations = {
position: gl.getAttribLocation(this._program, "a_position"),
texcoord: gl.getAttribLocation(this._program, "a_texcoord"),
matrix: gl.getUniformLocation(this._program, "u_matrix"),
textureMatrix: gl.getUniformLocation(this._program, "u_textureMatrix"),
texture: gl.getUniformLocation(this._program, "u_texture")
};
this._createBuffers();
}
_createBuffers() {
var positions;
var texcoords;
var gl;
gl = this._gl;
this._positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
positions = [0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
this._texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this._texcoordBuffer);
texcoords = [0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
}
async createTextureFromAsset(asset) {
var gl;
var tex;
var texData;
var img;
gl = this._gl;
tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
texData = {
width: 1,
height: 1,
texture: tex,
};
texData.width = asset.width;
texData.height = asset.height;
gl.bindTexture(gl.TEXTURE_2D, texData.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, asset);
return (texData);
}
//ctx.drawImage(tex, texWidth, texHeight, dstX, dstY);
//ctx.drawImage(tex, texWidth, texHeight, dstX, dstY, dstWidth, dstHeight)
drawImage(
tex, texWidth, texHeight,
srcX, srcY, srcWidth, srcHeight,
dstX, dstY, dstWidth, dstHeight, srcRotation) {
var gl;
var matrix, matrix2;
var texMatrix;
if (dstX === undefined) {
dstX = srcX;
srcX = 0;
}
if (dstY === undefined) {
dstY = srcY;
srcY = 0;
}
if (srcWidth === undefined) {
srcWidth = texWidth;
}
if (srcHeight === undefined) {
srcHeight = texHeight;
}
if (dstWidth === undefined) {
dstWidth = srcWidth;
srcWidth = texWidth;
}
if (dstHeight === undefined) {
dstHeight = srcHeight;
srcHeight = texHeight;
}
if (srcRotation === undefined) {
srcRotation = 0;
}
gl = this._gl;
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.useProgram(this._program);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.enableVertexAttribArray(this._locations.position);
gl.vertexAttribPointer(this._locations.position, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texcoordBuffer);
gl.enableVertexAttribArray(this._locations.texcoord);
gl.vertexAttribPointer(this._locations.texcoord, 2, gl.FLOAT, false, 0, 0);
matrix = mat4.create();
matrix2 = mat4.create();
mat4.ortho(matrix, 0, 1000, 1000, 0, -1, 1);
mat4.translate(matrix2, matrix, [dstX, dstY, 0]);
mat4.copy(matrix, matrix2);
mat4.scale(matrix2, matrix, [dstWidth, dstHeight, 1]);
mat4.copy(matrix, matrix2);
gl.drawingBufferHeight = 320;
gl.uniformMatrix4fv(this._locations.matrix, false, matrix);
texMatrix = mat4.create();
mat4.fromScaling(texMatrix, [1 / texWidth, 1 / texHeight, 1]);
mat4.translate(matrix2, texMatrix, [texWidth * 0.5, texHeight * 0.5, 0]);
mat4.copy(texMatrix, matrix2);
mat4.rotateZ(matrix2, texMatrix, srcRotation);
mat4.copy(texMatrix, matrix2);
mat4.translate(matrix2, texMatrix, [texWidth * -0.5, texHeight * -0.5, 0]);
mat4.translate(texMatrix, matrix2, [srcX, srcY, 0]);
mat4.scale(matrix2, texMatrix, [srcWidth, srcHeight, 1]);
mat4.copy(texMatrix, matrix2);
gl.uniformMatrix4fv(this._locations.textureMatrix, false, texMatrix);
gl.uniform1i(this._locations.texture, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
clear() {
var gl;
gl = this._gl;
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clear(gl.COLOR_BUFFER_BIT);
}
}
I have a blue screen with the clear function but nothing appears from drawImage function.
First off, please learn how to make a Minimal, Complete, and Verifiable example. Emphasis on minimal.
Looking at your code in drawImage you have the size of the canvas hard coded
mat4.ortho(matrix, 0, 1000, 1000, 0, -1, 1);
It seems like you'd want
mat4.ortho(matrix, 0, gl.canvas.width, gl.canvas.height, 0, -1, 1);
Also I have no idea what this line is for
gl.drawingBufferHeight = 320;
Finally I notice you have createTextureFromAsset as an async function but you'd not calling it with an await
const vertSrc = `
attribute vec4 a_position;
attribute vec2 a_texcoord;
uniform mat4 u_matrix;
uniform mat4 u_textureMatrix;
varying vec2 v_texcoord;
void main() {
gl_Position = u_matrix * a_position;
v_texcoord = (u_textureMatrix * vec4(a_texcoord, 0, 1)).xy;
}
`;
const fragSrc = `
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
if (v_texcoord.x < 0.0 ||
v_texcoord.y < 0.0 ||
v_texcoord.x > 1.0 ||
v_texcoord.y > 1.0) {
gl_FragColor = vec4(1, 0, 1, 1); // blue
return;
}
gl_FragColor = texture2D(u_texture, v_texcoord);
}
`;
class GLContext2D {
constructor(gl) {
var vert;
var frag;
this._gl = gl;
vert = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vert, vertSrc);
gl.compileShader(vert);
frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frag, fragSrc);
gl.compileShader(frag);
this._program = gl.createProgram();
gl.attachShader(this._program, vert);
gl.attachShader(this._program, frag);
gl.linkProgram(this._program);
this._locations = {
position: gl.getAttribLocation(this._program, "a_position"),
texcoord: gl.getAttribLocation(this._program, "a_texcoord"),
matrix: gl.getUniformLocation(this._program, "u_matrix"),
textureMatrix: gl.getUniformLocation(this._program, "u_textureMatrix"),
texture: gl.getUniformLocation(this._program, "u_texture")
};
this._createBuffers();
}
_createBuffers() {
var positions;
var texcoords;
var gl;
gl = this._gl;
this._positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
positions = [0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
this._texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this._texcoordBuffer);
texcoords = [0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
}
async createTextureFromAsset(asset) {
var gl;
var tex;
var texData;
var img;
gl = this._gl;
tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
texData = {
width: 1,
height: 1,
texture: tex,
};
texData.width = asset.width;
texData.height = asset.height;
gl.bindTexture(gl.TEXTURE_2D, texData.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, asset);
return (texData);
}
//ctx.drawImage(tex, texWidth, texHeight, dstX, dstY);
//ctx.drawImage(tex, texWidth, texHeight, dstX, dstY, dstWidth, dstHeight)
drawImage(
tex, texWidth, texHeight,
srcX, srcY, srcWidth, srcHeight,
dstX, dstY, dstWidth, dstHeight, srcRotation) {
var gl;
var matrix, matrix2;
var texMatrix;
if (dstX === undefined) {
dstX = srcX;
srcX = 0;
}
if (dstY === undefined) {
dstY = srcY;
srcY = 0;
}
if (srcWidth === undefined) {
srcWidth = texWidth;
}
if (srcHeight === undefined) {
srcHeight = texHeight;
}
if (dstWidth === undefined) {
dstWidth = srcWidth;
srcWidth = texWidth;
}
if (dstHeight === undefined) {
dstHeight = srcHeight;
srcHeight = texHeight;
}
if (srcRotation === undefined) {
srcRotation = 0;
}
gl = this._gl;
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.useProgram(this._program);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.enableVertexAttribArray(this._locations.position);
gl.vertexAttribPointer(this._locations.position, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texcoordBuffer);
gl.enableVertexAttribArray(this._locations.texcoord);
gl.vertexAttribPointer(this._locations.texcoord, 2, gl.FLOAT, false, 0, 0);
matrix = mat4.create();
matrix2 = mat4.create();
mat4.ortho(matrix, 0, gl.canvas.width, gl.canvas.height, 0, -1, 1);
mat4.translate(matrix2, matrix, [dstX, dstY, 0]);
mat4.copy(matrix, matrix2);
mat4.scale(matrix2, matrix, [dstWidth, dstHeight, 1]);
mat4.copy(matrix, matrix2);
// gl.drawingBufferHeight = 320;
gl.uniformMatrix4fv(this._locations.matrix, false, matrix);
texMatrix = mat4.create();
mat4.fromScaling(texMatrix, [1 / texWidth, 1 / texHeight, 1]);
mat4.translate(matrix2, texMatrix, [texWidth * 0.5, texHeight * 0.5, 0]);
mat4.copy(texMatrix, matrix2);
mat4.rotateZ(matrix2, texMatrix, srcRotation);
mat4.copy(texMatrix, matrix2);
mat4.translate(matrix2, texMatrix, [texWidth * -0.5, texHeight * -0.5, 0]);
mat4.translate(texMatrix, matrix2, [srcX, srcY, 0]);
mat4.scale(matrix2, texMatrix, [srcWidth, srcHeight, 1]);
mat4.copy(texMatrix, matrix2);
gl.uniformMatrix4fv(this._locations.textureMatrix, false, texMatrix);
gl.uniform1i(this._locations.texture, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
clear() {
var gl;
gl = this._gl;
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clear(gl.COLOR_BUFFER_BIT);
}
}
function loadImageP(url) {
return new Promise((fulfill, reject) => {
const img = new Image();
img.crossOrigin = "";
img.onload = fulfill;
img.onerror = reject;
img.src = url;
});
}
const gl = document.querySelector("canvas").getContext("webgl");
const gl2D = new GLContext2D(gl);
async function load(url) {
const e = await loadImageP(url);
const tex = await gl2D.createTextureFromAsset(e.target);
gl2D.drawImage(
tex.texture, tex.width, tex.height,
0, 0, 300, 150);
};
(async function() {
await load("http://i.imgur.com/iFom4eT.png");
}());
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
<canvas></canvas>
I am trying to draw a grid in a window using sdl2. The program when it is run, sometimes, the SDL_RenderPresent() even though being called, is not working resulting in a blank transparent window. Other times, the program is giving the correct output.
#include "SDL.h"
#include <stdio.h>
#include <stdlib.h>
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
const SDL_Color BLACK = { .r = 0, .g = 0, .b = 0, .a = 255 };
const SDL_Color WHITE = { .r = 255, .g = 255, .b = 255, .a = 255 };
const SDL_Color GRAY = { .r = 128, .g = 128, .b = 128, .a = 255 };
const SDL_Color RED = { .r = 255, .g = 0, .b = 0, .a = 255 };
const SDL_Color MAROON = { .r = 128, .g = 0, .b = 0, .a = 255 };
const SDL_Color BLUE = { .r = 0, .g = 0, .b = 255, .a = 255 };
const SDL_Color NAVY = { .r = 0, .g = 0, .b = 128, .a = 255 };
const SDL_Color LIME = { .r = 0, .g = 255, .b = 0, .a = 255 };
const SDL_Color GREEN = { .r = 0, .g = 128, .b = 0, .a = 255 };
const int P_SIZE = 10;
void draw_grid(SDL_Renderer *renderer)
{
SDL_Color prev;
SDL_GetRenderDrawColor(renderer, &prev.a, &prev.g, &prev.b, &prev.a);
SDL_SetRenderDrawColor(renderer, GRAY.r, GRAY.g, GRAY.b, GRAY.a);
// drawing the axes
SDL_RenderDrawLine(renderer, SCREEN_WIDTH / 2, 0,
SCREEN_WIDTH / 2, SCREEN_HEIGHT); // the Y-axis
SDL_RenderDrawLine(renderer, 0, SCREEN_HEIGHT / 2,
SCREEN_WIDTH, SCREEN_HEIGHT / 2); // the X-axis
SDL_SetRenderDrawColor(renderer, BLACK.r, BLACK.g, BLACK.b, BLACK.a);
// drawing the grid
for (int i = 0; i <= SCREEN_WIDTH; i += P_SIZE) {
if (i == SCREEN_WIDTH / 2) {
continue;
}
SDL_RenderDrawLine(renderer, i, 0, i, SCREEN_HEIGHT);
}
for (int i = 0; i <= SCREEN_HEIGHT; i += P_SIZE) {
if (i == SCREEN_HEIGHT / 2) {
continue;
}
SDL_RenderDrawLine(renderer, 0, i, SCREEN_WIDTH, i);
}
SDL_SetRenderDrawColor(renderer, prev.a, prev.g, prev.b, prev.a);
}
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "\nUnable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_Quit);
SDL_Window *window =
SDL_CreateWindow("Clipping",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN
);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
fprintf(stderr, "\nRenderer could not be created:%s\n", SDL_GetError());
return 1;
}
SDL_SetRenderDrawColor(renderer, WHITE.r, WHITE.g, WHITE.b, WHITE.a);
SDL_RenderClear(renderer);
draw_grid(renderer);
SDL_RenderPresent(renderer);
int quit = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = 1;
break;
default:
break;
}
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return 0;
}
I need to rotate picture by pressing arrows.
rotate(dots, 90, 150, 120, size.cx, size.cy);
PlgBlt(dc, dots, my_dc, 0, 0, size.cx, size.cy, my_mask, 0, 0);
There is a function - rotate.
But I don't know where to put this part. When I put it into WM_TIMER - happens nothing. In WM_PAINT - too. What's wrong?
Where put this code and where call this?
Here is WM_PAINT and WM_TIMER
case WM_PAINT:
dc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
BitBlt(mdc, 0, 0, info.bmWidth, info.bmHeight, bdc, 0, 0, SRCCOPY);
MaskBlt(mdc, my_pos.x, my_pos.y, my_size.cx, my_size.cy, my_dc, 0, 0, my_mask, 0, 0, MAKEROP4(SRCCOPY, SRCPAINT));
BitBlt(dc, 0, 0, rect.right, rect.bottom, mdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
break;
case WM_TIMER:
if(LOWORD(wParam) == 777u) {
if(GetAsyncKeyState(VK_LEFT))
{
if (GreatFuncLeftRight(my_pos.x,my_pos.y))
{
my_pos.x -= 2;
}
else my_pos.x-=0;
}
if(GetAsyncKeyState(VK_RIGHT))
{
if (GreatFuncLeftRightReverse(my_pos.x,my_pos.y))
{
my_pos.x += 2;
}
else my_pos.x+=0;
}
if(GetAsyncKeyState(VK_UP))
{
if (GreatFuncUpDown(my_pos.x,my_pos.y))
{
my_pos.y -= 2;
}
else my_pos.y-=0;// вверх
}
if(GetAsyncKeyState(VK_DOWN))
{
if (GreatFuncUpDownReverse(my_pos.x,my_pos.y))
{
my_pos.y += 2;
}
else my_pos.y+=0;
}
InvalidateRect(hwnd, NULL, FALSE);
}
break;