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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-443271.
//
// This file is part of the GLVis visualization tool and library. For more
// information and source code availability see https://glvis.org.
//
// GLVis is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef GLVIS_ATTR_TRAITS_HPP
#define GLVIS_ATTR_TRAITS_HPP
#include "renderer_core.hpp"
namespace gl3
{
struct AttrNone
{
static void setup() { }
static void setupLegacy(void*) { }
static void clear() { }
static void clearLegacy() { }
enum { exists = false };
};
// Base class to generate vertex attribute setup functions.
template<
typename TV, typename TAttr, TAttr TV::*Attrib, typename TAttrInfo>
struct AttrBase
{
constexpr static TAttr* getAttrOffset()
{
return &(((TV*)0)->*Attrib);
}
// Sets up vertex attributes in the currently-bound buffer object.
static void setup()
{
glEnableVertexAttribArray(TAttrInfo::ShaderIdx);
glVertexAttribPointer(TAttrInfo::ShaderIdx,
TAttrInfo::NumTuples,
TAttrInfo::AttrGLType,
TAttrInfo::NormalizeAttr,
sizeof(TV),
(void*) getAttrOffset());
}
// Sets up client-side vertex pointers for the given buffer.
static void setupLegacy(TV* buffer)
{
glEnableClientState(TAttrInfo::FFArrayIdx);
TAttrInfo::FFSetupFunc(TAttrInfo::NumTuples,
TAttrInfo::AttrGLType,
sizeof(TV),
(char*) buffer + (size_t) getAttrOffset());
}
// Disables the attribute array.
static void clear()
{
glDisableVertexAttribArray(TAttrInfo::ShaderIdx);
}
// Disables the client-side vertex array.
static void clearLegacy()
{
glDisableClientState(TAttrInfo::FFArrayIdx);
}
enum { exists = true };
};
// Default attribute traits for vertex types. Provides no-op setup/clear
// functions if an attribute doesn't exist.
template<typename TV, typename = int>
struct AttrCoord : AttrNone { };
template<typename TV, typename = int>
struct AttrNormal : AttrNone { };
template<typename TV, typename = int>
struct AttrColor : AttrNone { };
template<typename TV, typename = int>
struct AttrTexcoord : AttrNone { };
// Template specializations for attribute traits. If an attribute exists in a
// vertex, generates setup and clear functions which setup OpenGL vertex
// attributes.
//
// Each attribute specialization defines static parameters which are passed to
// the AttrBase base class via CRTP to generate the attribute setup functions:
// - AttrGLType: the OpenGL type of the attribute data
// - ShaderIdx: the index of the generic vertex attribute
// - FFArrayIdx: the index of the client-side vertex attribute array
// - FFSetupFunc: the function to use when setting up the FF array pointer;
// this can either be a direct pointer to a gl*Pointer function or a custom
// function
template<typename TV>
struct AttrCoord<TV, decltype((void)TV::coord, 0)>
: AttrBase<TV, decltype(TV::coord), &TV::coord,
AttrCoord<TV, decltype((void)TV::coord, 0)>>
{
constexpr static bool NormalizeAttr = false;
constexpr static int NumTuples = 3;
const static GLenum AttrGLType = GL_FLOAT;
const static int ShaderIdx = CoreGLDevice::ATTR_VERTEX;
const static GLenum FFArrayIdx = GL_VERTEX_ARRAY;
constexpr static auto FFSetupFunc = glVertexPointer;
};
template<typename TV>
struct AttrNormal<TV, decltype((void)TV::norm, 0)>
: AttrBase<TV, decltype(TV::norm), &TV::norm,
AttrNormal<TV, decltype((void)TV::norm, 0)>>
{
constexpr static bool NormalizeAttr = false;
constexpr static int NumTuples = 3;
const static GLenum AttrGLType = GL_FLOAT;
const static int ShaderIdx = CoreGLDevice::ATTR_NORMAL;
const static GLenum FFArrayIdx = GL_NORMAL_ARRAY;
static void FFSetupFunc(GLint /*size*/, GLenum type, GLsizei stride,
const GLvoid* ptr)
{
glNormalPointer(type, stride, ptr);
}
};
template<typename TV>
struct AttrColor<TV, decltype((void)TV::color, 0)>
: AttrBase<TV, decltype(TV::color), &TV::color,
AttrColor<TV, decltype((void)TV::color, 0)>>
{
constexpr static bool NormalizeAttr = true;
constexpr static int NumTuples = 4;
const static GLenum AttrGLType = GL_UNSIGNED_BYTE;
const static int ShaderIdx = CoreGLDevice::ATTR_COLOR;
const static GLenum FFArrayIdx = GL_COLOR_ARRAY;
constexpr static auto FFSetupFunc = glColorPointer;
};
template<typename TV>
struct AttrTexcoord<TV, decltype((void)TV::texCoord, 0)>
: AttrBase<TV, decltype(TV::texCoord), &TV::texCoord,
AttrTexcoord<TV, decltype((void)TV::texCoord, 0)>>
{
constexpr static bool NormalizeAttr = false;
constexpr static int NumTuples = 1;
const static GLenum AttrGLType = GL_FLOAT;
const static int ShaderIdx = CoreGLDevice::ATTR_TEXCOORD0;
const static GLenum FFArrayIdx = GL_TEXTURE_COORD_ARRAY;
constexpr static auto FFSetupFunc = glTexCoordPointer;
};
}
#endif // GLVIS_ATTR_TRAITS_HPP
|