File: webgl_array_of_structs_uniform.c

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (121 lines) | stat: -rw-r--r-- 3,376 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * Copyright 2018 The Emscripten Authors.  All rights reserved.
 * Emscripten is available under two separate licenses, the MIT license and the
 * University of Illinois/NCSA Open Source License.  Both these licenses can be
 * found in the LICENSE file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#include <GLES2/gl2.h>
#include <GLES3/gl3.h>

GLuint compile_shader(GLenum shaderType, const char *src)
{
  GLuint shader = glCreateShader(shaderType);
  glShaderSource(shader, 1, &src, NULL);
  glCompileShader(shader);

  GLint isCompiled = 0;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
  if (!isCompiled)
  {
    GLint maxLength = 0;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
    char *buf = (char*)malloc(maxLength+1);
    glGetShaderInfoLog(shader, maxLength, &maxLength, buf);
    printf("%s\n", buf);
    free(buf);
    return 0;
  }

   return shader;
}

GLuint create_program(GLuint vertexShader, GLuint fragmentShader)
{
   GLuint program = glCreateProgram();
   glAttachShader(program, vertexShader);
   glAttachShader(program, fragmentShader);
   glBindAttribLocation(program, 0, "apos");
   glBindAttribLocation(program, 1, "acolor");
   glLinkProgram(program);
   return program;
}

int main()
{
  EmscriptenWebGLContextAttributes attr;
  emscripten_webgl_init_context_attributes(&attr);
  attr.majorVersion = 2;
  EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context("#canvas", &attr);
  emscripten_webgl_make_context_current(ctx);

  static const char vertex_shader[] =
    "#version 300 es\n"
    "in vec4 apos;\n"
    "in int idx;\n"
    "struct S { vec4 color; };\n"
    "uniform S colors[3];\n"
    "out vec4 color;\n"
    "void main() {\n"
      "color = colors[idx].color;\n"
      "gl_Position = apos;\n"
    "}\n";
  GLuint vs = compile_shader(GL_VERTEX_SHADER, vertex_shader);

  static const char fragment_shader[] =
    "#version 300 es\n"
    "precision lowp float;\n"
    "in vec4 color;\n"
    "out vec4 fragColor;\n"
    "void main() {\n"
      "fragColor = color;\n"
    "}\n";
  GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);

  GLuint program = create_program(vs, fs);
  glUseProgram(program);

  struct P
  {
    float x, y;
    int idx;
  };

  static const struct P pos_and_idx[] = {
     { -0.6f, -0.6f, 0 },
     {  0.6f, -0.6f, 1 },
     {  0.f,   0.6f, 2 }
  };

  GLuint vbo;
  glGenBuffers(1, &vbo);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, sizeof(pos_and_idx), pos_and_idx, GL_STATIC_DRAW);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 12, 0);
  glVertexAttribIPointer(1, 1, GL_INT, 12, (void*)8);

  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);

  float red[4]   = { 1.0f, 0.f, 0.0f, 1.0f };
  float green[4] = { 0.0f, 1.f, 0.0f, 1.0f };
  float blue[4]  = { 0.0f, 0.f, 1.0f, 1.0f };
  int loc = glGetUniformLocation(program, "colors[0].color");
  assert(loc >= 0);
  glUniform4fv(loc, 1, red);
  loc = glGetUniformLocation(program, "colors[1].color");
  assert(loc >= 0);
  glUniform4fv(loc, 1, green);
  loc = glGetUniformLocation(program, "colors[2].color");
  assert(loc >= 0);
  glUniform4fv(loc, 1, blue);
  glClearColor(0.3f,0.3f,0.3f,1);
  glClear(GL_COLOR_BUFFER_BIT);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  return 0;
}