Skip to content

Commit

Permalink
Add zooming, move to SDL 2.0, fix stbi load
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean Voisen committed Mar 5, 2018
1 parent 4a14698 commit fbc1e5c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 39 deletions.
39 changes: 18 additions & 21 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,34 @@ const ImageViewer = {};

function Program(container, canvas) {
const init = Module.initializeOpenGL(canvas.width, canvas.height);
this.zoom = 1.0;
this._setupDragDrop();
this._setupMouseWheel(canvas);
this._invalidate();
};

Program.prototype.render = function () {
Module.render();
};

Program.prototype._invalidate = function () {
window.requestAnimationFrame(this.render.bind(this));
window.requestAnimationFrame(() => Module.render(this.zoom));
}

Program.prototype._setupMouseWheel = function(canvas) {
canvas.addEventListener('mousewheel', this._handleMouseWheel.bind(this));
canvas.addEventListener('DOMMouseScroll', this._handleMouseWheel.bind(this));
}

Program.prototype._setupDragDrop = function () {
document.addEventListener('dragover', this._handleDragOver.bind(this));
document.addEventListener('drop', this._handleDrop.bind(this));
}

Program.prototype._handleMouseWheel = function(event) {
event.stopPropagation();
event.preventDefault();
const delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail));
this.zoom = Math.max(0, this.zoom + delta * 0.05);
this._invalidate();
}

Program.prototype._handleDragOver = function (event) {
event.stopPropagation();
event.preventDefault();
Expand All @@ -34,8 +45,7 @@ const ImageViewer = {};
if (files && files.length === 1 && files[0].type.match('image/jpeg')) {
const fileReader = new FileReader();
fileReader.onload = (event) => {
if (this._loadImageCopyToHeapCwrap(new Uint8Array(event.target.result))) {
// if (this._loadImageCopyToHeapCallDirect(new Uint8Array(event.target.result))) {
if (this._loadImage(new Uint8Array(event.target.result))) {
this._invalidate();
}
};
Expand All @@ -50,7 +60,7 @@ const ImageViewer = {};
}
}

Program.prototype._loadImageCopyToHeapCwrap = function (imageData) {
Program.prototype._loadImage = function (imageData) {
const startTime = new Date();
const numBytes = imageData.length * imageData.BYTES_PER_ELEMENT;
const dataPtr = Module._malloc(numBytes);
Expand All @@ -63,19 +73,6 @@ const ImageViewer = {};
return didLoad;
}

Program.prototype._loadImageCopyToHeapCallDirect = function (imageData) {
const startTime = new Date();
const numBytes = imageData.length * imageData.BYTES_PER_ELEMENT;
const dataPtr = Module._malloc(numBytes);
const dataOnHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, numBytes);
dataOnHeap.set(imageData);
const didLoad = Module._loadJPEGImage(dataOnHeap.byteOffset, imageData.length);
Module._free(dataPtr);
console.log('[Copy to Heap (Direct)] Time to load: ' + (new Date() - startTime));

return didLoad;
}

ImageViewer.run = function (container, canvas) {
new Program(container, canvas);
};
Expand Down
1 change: 1 addition & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ CC=emcc
SRC=renderer.cpp
CFLAGS=-Werror -std=c++11 -O2 -g0
EMSCRIPTEN_FLAGS=-s USE_WEBGL2=1 \
-s USE_SDL=2 \
-s WASM=1 \
-s TOTAL_MEMORY=134217728 \
-s EXPORTED_FUNCTIONS='["_initializeOpenGL", "_render", "_loadJPEGImage"]'
Expand Down
43 changes: 26 additions & 17 deletions renderer.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#include <iostream>
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include <SDL/SDL.h>
#include <SDL2/SDL.h>
#include <emscripten.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

SDL_Surface *screen;
SDL_Window *window;
SDL_GLContext glContext;
GLuint program;
GLuint texture;
bool textureLoaded = false;
Expand All @@ -22,13 +23,14 @@ GLfloat planeVertices[] = {
};

const char vertexShaderSrc[] =
"#version 300 es \n"
"in vec4 vert; \n"
"out vec2 texCoord; \n"
"void main() { \n"
" gl_Position = vert; \n"
"#version 300 es \n"
"uniform float zoom; \n"
"in vec4 vert; \n"
"out vec2 texCoord; \n"
"void main() { \n"
" gl_Position = vec4(vert.xy * zoom, 0.0f, 1.0f); \n"
" texCoord = vec2((vert.x + 1.0f) / 2.0f, (1.0f - vert.y) / 2.0);\n"
"} \n";
"} \n";

const char fragmentShaderSrc[] =
"#version 300 es \n"
Expand Down Expand Up @@ -83,13 +85,16 @@ extern "C" {

int initializeOpenGL(int width, int height)
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == 0) {
screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == 0) {
window = SDL_CreateWindow("Image Viewer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
} else {
std::cerr << "Error initializing SDL: " << SDL_GetError() << std::endl;
return 0;
}

glContext = SDL_GL_CreateContext(window);
SDL_EventState(SDL_MOUSEWHEEL, SDL_IGNORE);

GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSrc);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
program = buildProgram(vertexShader, fragmentShader, "vert");
Expand All @@ -100,7 +105,7 @@ int initializeOpenGL(int width, int height)
return 1;
}

void render() {
void render(float zoom) {
glClear(GL_COLOR_BUFFER_BIT);

if (!textureLoaded) {
Expand Down Expand Up @@ -131,6 +136,10 @@ void render() {
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);

// Set zoom
GLuint zoomUniform = glGetUniformLocation(program, "zoom");
glUniform1f(zoomUniform, zoom);

// Draw
glDrawArrays(GL_TRIANGLES, 0, 6);

Expand All @@ -139,7 +148,7 @@ void render() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

SDL_GL_SwapBuffers();
SDL_GL_SwapWindow(window);
}

int loadJPEGImage(uint8_t* buffer, size_t size) {
Expand All @@ -150,22 +159,22 @@ int loadJPEGImage(uint8_t* buffer, size_t size) {
}

int width, height, channels;
uint8_t* imageData = stbi_load_from_memory(buffer, static_cast<int>(size), &width, &height, &channels, 0);
uint8_t* imageData = stbi_load_from_memory(buffer, static_cast<int>(size), &width, &height, &channels, STBI_rgb_alpha);
if (!imageData) {
std::cerr << "Error loading image" << std::endl;
return 0;
}

std::cout << "Loaded image with dimensions " << width << "x" << height << " and size " << size << std::endl;
std::cout << "Loaded image with dimensions " << width << "x" << height << ", size " << size << ", and channels " << channels << std::endl;

// Generate texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);

Expand Down
2 changes: 1 addition & 1 deletion renderer_post.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Module['initializeOpenGL'] = Module.cwrap('initializeOpenGL', 'number', ['number', 'number']);
Module['render'] = Module.cwrap('render', 'void', []);
Module['render'] = Module.cwrap('render', 'void', ['number']);
Module['loadJPEGImage'] = Module.cwrap('loadJPEGImage', 'number', ['number', 'number']);

0 comments on commit fbc1e5c

Please sign in to comment.