- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
介绍
我正在构建一个简单的wavefront .obj文件解析器。我设法使其读取文件,存储了文件的内容(顶点位置,顶点坐标,顶点法线(尚未使用)和多边形面元素信息(例如5/2/3))。然后将此数据传递到一个类(称为GameEntity),并从那里开始使用GL_TRIANGLES模式下的glDrawElements将数据用于将该特定实体(在这种情况下为立方体)呈现到呈现循环内的屏幕。但是,纹理渲染不正确。
源代码
OBJLoader.java
public class OBJLoader {
/**
* This method loads a model represented by a wavefront .obj file from resources/models using
* the specified name of the file (without the .obj extension) and a full path to the texture used
* by the model. It passes the information (vertex positions, texture coordinates, indices)
* obtained from the .obj file to the GameEntity constructor.
* @param fileName
* @param texturePath
* @return
* @throws Exception
*/
public static GameEntity loadObjModel(String fileName, String texturePath) throws Exception {
double start = System.nanoTime();
List<Vector3f> vertices = null;
List<Vector2f> textures = null;
List<Vector3f> normals = null;
List<Integer> indices = null;
String line;
float[] vertexPosArray = null;
float[] texturesArray = null;
float[] normalsArray = null;
int[] indicesArray = null;
try {
FileReader fr = new FileReader(new File("resources/models/" + fileName + ".obj"));
BufferedReader br = new BufferedReader(fr);
vertices = new ArrayList<>();
textures = new ArrayList<>();
normals = new ArrayList<>();
indices = new ArrayList<>();
while((line = br.readLine()) != null) {
if (!line.equals("") || !line.startsWith("#")) {
String[] splitLine = line.split(" ");
switch(splitLine[0]) {
case "v":
Vector3f vertex = new Vector3f(Float.parseFloat(splitLine[1]), Float.parseFloat(splitLine[2]), Float.parseFloat(splitLine[3]));
vertices.add(vertex);
System.out.println("[OBJLoader.loadObjModel]: Vertex " + vertex.toString() + " has been added to vertices from " + fileName);
break;
case "vt":
Vector2f texture = new Vector2f(Float.parseFloat(splitLine[1]), Float.parseFloat(splitLine[2]));
textures.add(texture);
System.out.println("[OBJLoader.loadObjModel]: Texture coordinate [" + texture.x + ", " + texture.y + "] has been added to textures from " + fileName);
break;
case "vn":
Vector3f normal = new Vector3f(Float.parseFloat(splitLine[1]), Float.parseFloat(splitLine[2]), Float.parseFloat(splitLine[3]));
normals.add(normal);
System.out.println("[OBJLoader.loadObjModel]: Normal " + normal + " has been added to normals from " + fileName);
break;
}
}
}
int numVertices = vertices.size();
System.out.println("[OBJLoader.loadObjModel]: numVertices = " + numVertices);
texturesArray = new float[numVertices*2];
System.out.println("[OBJLoader.loadObjModel]: length of texturesArray = " + texturesArray.length);
normalsArray = new float[numVertices*3];
br.close(); //find a better way to start a file again
br = new BufferedReader(new FileReader("resources/models/" + fileName + ".obj"));
while((line = br.readLine()) != null) {
if (line.startsWith("f")) {
System.out.println(" [OBJLoader.loadObjModel]: Found line starting with f!");
String[] splitLine = line.split(" ");
//f should be omitted, therefore not starting at index 0
String[] v1 = splitLine[1].split("/");
String[] v2 = splitLine[2].split("/");
String[] v3 = splitLine[3].split("/");
System.out.println(" v1 | " + v1[0] + ", " + v1[1] + ", " + v1[2]);
System.out.println(" v2 | " + v2[0] + ", " + v2[1] + ", " + v2[2]);
System.out.println(" v3 | " + v3[0] + ", " + v3[1] + ", " + v3[2]);
processVertex(v1, indices, textures, normals, texturesArray, normalsArray);
processVertex(v2, indices, textures, normals, texturesArray, normalsArray);
processVertex(v3, indices, textures, normals, texturesArray, normalsArray);
}
}
br.close();
} catch (Exception e) {
System.err.println("[OBJLoader.loadObjModel]: Error loading obj model!");
e.printStackTrace();
}
vertexPosArray = new float[vertices.size()*3];
indicesArray = new int[indices.size()];
int i = 0;
for(Vector3f vertex : vertices) {
vertexPosArray[i++] = vertex.x;
vertexPosArray[i++] = vertex.y;
vertexPosArray[i++] = vertex.z;
}
for(int j = 0; j<indices.size(); j++) {
indicesArray[j] = indices.get(j);
}
double end = System.nanoTime();
double delta = (end - start) / 1000_000;
System.out.println("[OBJLoader.loadObjModel]: Vertices array of " + fileName + ": ");
System.out.println("[OBJLoader.loadObjModel]: It took " + delta + " milliseconds to load " + fileName);
System.out.println("[OBJLoader.loadObjModel]: Ordered vertex position array: " + ArrayUtils.getFloatArray(vertexPosArray));
System.out.println("[OBJLoader.loadObjModel]: Ordererd texture coordinates array: " + ArrayUtils.getFloatArray(texturesArray));
System.out.println("[OBJLoader.loadObjModel]: Ordererd indices array: " + ArrayUtils.getIntArray(indicesArray));
return new GameEntity(vertexPosArray, indicesArray, texturesArray, texturePath);
}
/**
* The input to this method is vertex data as a String array, which is used to determine how to
* arrange texture coordinate and normal vector data (this data is associated with each vertex position)
* into the correct order in the texture and normals array
* @param vertexData
* @param indices
* @param textrues
* @param normals
* @param textureArray
* @param normalsArray
*/
private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures,
List<Vector3f> normals, float[] textureArray, float[] normalsArray) {
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
System.out.println("[OBJLoader.processVertex]: currentVertexPointer = " + currentVertexPointer);
indices.add(currentVertexPointer);
System.out.println("[OBJLoader.processVertex]: Adding " + currentVertexPointer + " to indices!");
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2 + 1] = 1.0f - currentTex.y;
System.out.println("[OBJLoader.processVertex]: Added vt " + currentTex.x + " to index " + currentVertexPointer*2 +
" and vt " + (1.0f - currentTex.y) + " to index " + (currentVertexPointer*2+1) + " of the textureArray");
Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2]) - 1);
normalsArray[currentVertexPointer*3] = currentNorm.x;
normalsArray[currentVertexPointer*3 + 1] = currentNorm.y;
normalsArray[currentVertexPointer*3 + 2] = currentNorm.z;
}
}
/**
* Creates a new textured GameEntity
* @param vPositions The vertex coordinates of a model
* @param indices The indices of a model (in which order should the vertices be bound by OpenGL?)
* @param textureCoordinates The coordinates of a texture (which texture coordinate should be applied to which vertex?)
* @param texturePath The path of the texture
* @throws Exception
*/
public GameEntity(float[] vPositions, int[] indices, float[] textureCoordinates, String texturePath) throws Exception{
System.out.println("[GameEntity.GameEntity]: Creating a new model texture...");
modelTexture = new Texture(texturePath);
System.out.println("[GameEntity.GameEntity]: Creating new mesh based on parameters... ");
mesh = new Mesh(vPositions, indices, textureCoordinates, modelTexture);
System.out.println("[GameEntity.GameEntity]: Initializing position, scale and rotation instance fields... ");
position = new Vector3f(0, 0, 0);
scale = 1;
rotation = new Vector3f(0, 0, 0);
}
/**
* This constructor creates a renderable object (instance of Mesh with its texture) out of input parameters by storing them
* in the vao of that Mesh instance
* @param vertices The vertex positions of a model
* @param indices The indices to tell OpenGL how to connect the vertices
* @param texCoords Texture coordinates (used for texture mapping)
* @param texture A Texture object
*/
public Mesh(float[] vertices, int[] indices, float[] texCoords, renderEngine.Texture texture) {
System.out.println("[Mesh.Mesh]: Creating a new textured Mesh instance... ");
verticesBuffer = null;
textureBuffer = null;
indicesBuffer = null;
try {
this.texture = texture;
vertexCount = indices.length;
vbos = new ArrayList<>();
vaos = new ArrayList<>();
textures = new ArrayList<>();
System.out.println("[Mesh] Creating and binding the vao (vaoID)");
vaoID = glGenVertexArrays();
vaos.add(vaoID);
glBindVertexArray(vaoID);
setupVerticesVbo(vertices);
setupIndicesBuffer(indices);
setupTextureVbo(texCoords);
textures.add(texture);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
}
setupIndicesBuffer
和
setupTextureVbo
:
private void setupIndicesBuffer(int[] indices) {
indicesVboID = glGenBuffers();
vbos.add(indicesVboID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVboID);
indicesBuffer = BufferUtilities.storeDataInIntBuffer(indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
}
/**
* This method sets up the texture vbo for a mesh object (buffers data to it and assigns it to attribute list
* index 1 of the vao)
*
* @param colours - an array of colours of the vertices of a model
*/
private void setupTextureVbo(float[] textures) {
System.out.println("[Mesh] Creating texture vbo (textureVboID)...");
textureVboID = glGenBuffers();
vbos.add(textureVboID);
System.out.println(" - [Mesh] Creating texture buffer (textureBuffer)...");
textureBuffer = BufferUtilities.storeDataInFloatBuffer(textures);
System.out.println(" - [Mesh] Binding textureVboID to GL_ARRAY_BUFER...");
glBindBuffer(GL_ARRAY_BUFFER, textureVboID);
System.out.println(" - [Mesh] Buffering data from textureBuffer to GL_ARRAY_BUFFER...");
glBufferData(GL_ARRAY_BUFFER, textureBuffer, GL_STATIC_DRAW);
System.out.println(" - [Mesh] Sending texture vbo to index 1 of the active vao...");
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
}
# Blender v2.78 (sub 0) OBJ File: 'cube.blend'
# www.blender.org
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.2766 0.2633
vt 0.5000 0.4867
vt 0.2766 0.4867
vt 0.7234 0.4867
vt 0.9467 0.2633
vt 0.9467 0.4867
vt 0.0533 0.4867
vt 0.0533 0.2633
vt 0.2766 0.0400
vt 0.5000 0.2633
vt 0.0533 0.7100
vt 0.7234 0.2633
vt 0.0533 0.0400
vt 0.2766 0.7100
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 -0.0000 0.0000
vn 0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
s off
f 2/1/1 4/2/1 1/3/1
f 8/4/2 6/5/2 5/6/2
f 5/7/3 2/1/3 1/3/3
f 6/8/4 3/9/4 2/1/4
f 3/10/5 8/4/5 4/2/5
f 1/3/6 8/11/6 5/7/6
f 2/1/1 3/10/1 4/2/1
f 8/4/2 7/12/2 6/5/2
f 5/7/3 6/8/3 2/1/3
f 6/8/4 7/13/4 3/9/4
f 3/10/5 7/12/5 8/4/5
f 1/3/6 4/14/6 8/11/6
case "vt":
Vector2f texture = new Vector2f(Float.parseFloat(splitLine[1]), Float.parseFloat(splitLine[2]));
textures.add(texture);
break;
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
indices.add(currentVertexPointer);
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2 + 1] = 1.0f - currentTex.y;
f
开头来描述。每条这样的线描述三个顶点。每个顶点由顶点位置,纹理坐标和法线向量表示。这样的行的示例:
f 8/4/2 6/5/2 5/6/2
。仔细查看
8/4/2
顶点表示。这表明该顶点的位置等于.obj文件中的第八个指定顶点位置(
-1.000000 1.000000 -1.000000
),纹理坐标等于文件中的第四个指定纹理坐标(
0.7234 0.4867
)和第二法向矢量(0.0000 1.0000 0.0000 )。
8/4/2
,一次用于
6/5/2
,一次对于
5/6/2
)。每次,一组数据作为String数组(在正斜杠的位置分割)传递给该方法,然后是List纹理,List法线,float [] textureArray和float [] normalsArray。
private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures,
List<Vector3f> normals, float[] textureArray, float[] normalsArray) {
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
System.out.println("[OBJLoader.processVertex]: currentVertexPointer = " + currentVertexPointer);
indices.add(currentVertexPointer);
System.out.println("[OBJLoader.processVertex]: Adding " + currentVertexPointer + " to indices!");
//something probably wrong here
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2 + 1] = 1.0f - currentTex.y;
System.out.println("[OBJLoader.processVertex]: Added vt " + currentTex.x + " to index " + currentVertexPointer*2 +
" and vt " + (1.0f - currentTex.y) + " to index " + (currentVertexPointer*2+1) + " of the textureArray");
Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2]) - 1);
normalsArray[currentVertexPointer*3] = currentNorm.x;
normalsArray[currentVertexPointer*3 + 1] = currentNorm.y;
normalsArray[currentVertexPointer*3 + 2] = currentNorm.z;
}
8/4/2
作为参数传递,则将7分配给currentVertexPointer)。减去一个的原因是wavefront .obj文件中的图像从1开始,而Java中的索引从0开始。然后,将此数字添加到索引List中。
8/4/2
作为参数传递,则Vector3f),从纹理列表中获取相应的纹理坐标(表示为Vector2f)。将获得纹理列表的索引3):
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
textureArray[currentVertexPointer*2] = currentTex.x;
。第二个纹理坐标(某些情况下为v或t)存储在textureArray的索引处,该索引比第一个纹理坐标的索引大:
textureArray[currentVertexPointer*2 + 1] = 1.0f - currentTex.y;
。
Index | values that get assigned to the index during execution of the program
0 | 0.2766 ... 0.2766 (third f-call) ... 0.2766 (sixth f-call) ... 0.2766 (14th f-call)
1 | 0.5133 ... 0.5133 (third f-call) ... 0.5133 (sixth f-call) ... 0.5133 (14th f-call)
2 | 0.2766 ... 0.2766 (third f-call) ... 0.2766 (fourth f-call) ... 0.2766 (seventh f-call) ... 0.2766 (ninth f-call)
3 | 0.7367 ... 0.7367 (third f-call) ... 0.7367 (fourth f-call) ... 0.7367 (seventh f-call) ... 0.7367 (ninth f-call)
4 | 0.2766 ... 0.5 (fifth f-call) ... 0.5 (seventh f-call) ... 0.2766 (twelveth f-call) ... 0.5 (13th f-call)
5 | 0.96 ... 0.7367 (fifth f-call) ... 0.7367 (seventh f-call) ... 0.96 (twelveth f-call) ... 0.7367 (13th f-call)
6 | 0.5 ... 0.5 (fifth f-call) ... 0.5 (seventh f-call) ... 0.2766 (14th f-call)
7 | 0.5133 ... 0.5133 (fifth f-call) ... 0.5133 (seventh f-call) ... 0.29000002 (14th f-call)
8 | 0.9467 ... 0.0533 (third f-call) ... 0.0533 (sixth f-call) ... 0.0533 (ninth f-call)
9 | 0.5133 ... 0.5133 (third f-call) ... 0.5133 (sixth f-call) ... 0.5133 (ninth f-call)
10 | 0.9467 ... 0.0533 (fourth f-call) ... 0.9467 (eighth f-call) ... 0.0533 (ninth f-call) ... 0.0533 (twelveth f-call)
11 | 0.7367 ... 0.7367 (fourth f-call) ... 0.7367 (eighth f-call) ... 0.7367 (ninth f-call) ... 0.7367 (twelveth f-call)
12 | 0.7234 ... 0.0533 (twelveth f-call) ... 0.7234 (13th f-call)
13 | 0.7367 ... 0.96 (twelveth f-call) ... 0.7367 (13th f-call)
14 | 0.7234 ... 0.7234 (fifth f-call) ... 0.0533 (sixth f-call) ... 0.7234 (eighth f-call) ... 0.7234 (13th f-call) ... 0.0533 (14th f-call)
15 | 0.5133 ... 0.5133 (fifth f-call) ... 0.29000002 (sixth f-call) ... 0.5133 (eighth f-call) ... 0.5133 (13th f-call) ... 0.29000002 (14th f-call)
All of the indexes in the texturesArray have been accessed and assigned values several time.
Indexes with unchanged values (ie, indexes which have been assigned the same value every time):
0, 1, 2, 3, 9, 11
Indexes with changed value (ie, indexes which have been assigned different values):
4, 5, 6, 7, 8, 10, 12, 13, 14
private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures,
List<Vector3f> normals, float[] textureArray, float[] normalsArray) {
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
System.out.println("[OBJLoader.processVertex]: currentVertexPointer = " + currentVertexPointer);
indices.add(currentVertexPointer);
//THIS IS NEW
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1]) - 1);
if ((textureArray[currentVertexPointer*2] + textureArray[currentVertexPointer*2+1])== 0 ) { //if the index hasn't been populated yet, store it
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2+1] = 1.0f - currentTex.y;
} else {
//create a new vertex (index?) and associate it with second coordinate u
//create a new vertex (index?) and associate it with texture coordinate v
}
//END OF NEW CODE
Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2]) - 1);
normalsArray[currentVertexPointer*3] = currentNorm.x;
normalsArray[currentVertexPointer*3 + 1] = currentNorm.y;
normalsArray[currentVertexPointer*3 + 2] = currentNorm.z;
}
8/4/2
)获得的纹理坐标。
processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures, List<Vector3f> normals, float[] textureArray, float[] normalsArray)
方法的情况下,这些重复的矢量应存储在哪里?您是否应该只复制此位置向量的索引,然后为该索引分配纹理坐标?然后应该如何将纹理坐标存储到这一新索引?
if ((textureArray[currentVertexPointer*2] + textureArray[currentVertexPointer*2+1])== 0 ) { //if the index hasn't been populated yet, store it
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2+1] = 1.0f - currentTex.y;
} else {
int duplicateVertexPointer = currentVertexPointer;
indices.add(duplicateVertexPointer);
textureArray[duplicateVertexPointer*2] = currentTex.x;
textureArray[duplicateVertexPointer*2+1] = currentTex.y;
}
最佳答案
看来您非常接近找出问题所在。是的,某些数据正在被覆盖,因为obj顶点可以在不同的面上具有多个法线或纹理矢量。问题在于,openGL中的顶点属性不是这种情况。
您需要做的是检查您的顶点是否已经具有纹理坐标,是否创建了一个新的顶点并将其与第二个纹理相关联。请注意,这可能会有些混乱。
假设您有一个顶点v1。在不同的面孔上它有几个纹理坐标。
V1-> t1; v1-> t2; v1-> t2。
所以您说V1-> t1,很简单。但是随后您在同一顶点上看到另一个坐标。因此,您克隆了v1,并得到v2-> t2(其中v1 == v2)。
现在是v1-> t2,您不应该创建一个新的顶点v3,因为v2已经存在并且非常适合。
因此,要正确执行此操作,您需要跟踪克隆,并查看它们是否适合组合索引/坐标。
当同时具有法线和纹理坐标时,它变得更加混乱,因为两个面可以共享纹理坐标,但不能共享法线或相反,所有共存都存在。因此,有时您会拥有一个适合特定组合但并非全部适合的克隆。
我做了一个工作正常的obj解析器,但是有点杂乱,所以给您代码将是一种损害。我希望至少能使您走上正确的路。
如果要再次创建解析器,请按以下步骤进行编辑。
每当我在脸上添加一个顶点时,我都会调用以下函数:
vector<vertex> vertices; //All the vertices in my object, this includes the position, texture coordinate and normal
vector<vector<int>> synonyms; // For each vertex, the array of vertices which are the same (cloned vertices)
vector<int> normalIndex;
vector<int> UV index;
int normalIn;
int textureIn;
int vertexIn; //each elements in one point of my face declaration in the obj file vertexIn/textureIn/normalIn
funtion(all of the above)
{
vector<int> synonymsVertex = synonyms[vertexIn]; //We get the synonyms of the vertex we want to add
for(int vertexClone : synonymsVertex)
{
vertex vertexObj = vertices[vertexClone];
//In the case the combination doesn't exist, we clone the vertex and add it to the list
if(vertexObj.normal != normalIn || vertexObj.UV != textureIn)
{
vertex newVertex(vertexObj, normalIn, textureIn);
vertices.push_back(newVertex);
synonymsVertex.push_back(vertices.size - 1);
}
}
}
关于java - 尝试从波前.obj文件加载纹理时,为什么在使用索引渲染(glDrawElements)时纹理显示不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50806126/
我有一个未定义数量的显示上下文,每个都将显示一个纹理。当我调用 glGenTextures 时,我会在所有显示上下文中返回相同的名称。这会起作用吗?即使它们具有相同的名称,它们仍会存储和显示不同的纹理
我在 SVG 中看到过:文本填充是图像而不是颜色;我一直想知道使用 CSS3 是否可以实现这样的事情。 我浏览了整个网络,到目前为止只找到了基本上将图像覆盖在文本上的解决方法(请参阅 this ,这对
我是 WebGL 的新手。 :)我知道顶点数据和纹理不应该经常更新,但是当它们确实发生变化时,首选哪个:- 通过调用 gl.deleteBuffer 销毁先前的缓冲区 (static_draw) 并创
我需要将 GL_RGBA32F 作为内部格式,但我在 OpenGL ES 实现中没有得到它。相反,我只得到 GL_FLOAT 作为纹理数据类型。 OES_texture_float 规范没有说明里面的
当我执行某些几何体的渲染时,我可以在控制台中看到此警告: THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter sho
我正在尝试使用阴影贴图实现阴影,因此我需要将场景渲染到单独的帧缓冲区(纹理)。我无法让它正常工作,因此在剥离我的代码库后,我留下了一组相对简单的指令,这些指令应该将场景渲染到纹理,然后简单地渲染纹理。
我在 XNA 中使用带有自定义着色器的标准 .fbx 导入器。当我使用 BasicEffect 时,.fbx 模型被 UV 正确包裹并且纹理正确。但是,当我使用我的自定义效果时,我必须将纹理作为参数加
如果我创建一个 .PNG 1024 x 1024 的纹理并在中间画一个 124 x 124 的圆,它周围是空的,它使用的 RAM 量是否与我画一个 124 x 的圆一样124 x 124 空间上的 1
我试图在 Android 中绘制一个地球仪,为此我使用了 OpenGL。然而,为了让它更容易理解,我将从制作一个简单的 3D 立方体开始。我使用 Blender 创建我的 3D 对象(立方体),并在我
文本本身的背景图像层是否有任何 JS/CSS 解决方案? 示例 最佳答案 检查这个http://lea.verou.me/2012/05/text-masking-the-standards-way/
非功能代码: if sprite.texture == "texture" { (code) } 当 Sprite 具有特定纹理时,我正在尝试访问 Sprite 的纹理以运行代码。目前纹理仅在我的
我正在尝试学习适用于 iOS 的 SceneKit 并超越基本形状。我对纹理的工作原理有点困惑。在示例项目中,平面是一个网格,并对其应用了平面 png 纹理。你如何“告诉”纹理如何包裹到物体上?在 3
基本上, 这有效: var expl1 = new THREE.ImageUtils.loadTexture( 'images/explodes/expl1.png' ); this.material
我正在尝试将各种场景渲染为一组纹理,每个场景都有自己的纹理到应该绘制的位置...... 问题: 创建 512 个 FBO,每个 FBO 绑定(bind)了 512 个纹理,这有多糟糕。只使用一个 FB
我正在使用文本 protobuf 文件进行系统配置。 我遇到的一个问题是序列化的 protobuf 格式不支持注释。 有没有办法解决? 我说的是文本序列化数据格式,而不是方案定义。 这个问题是有人在某
我想将我的 3D 纹理的初始化从 CPU 移到 GPU。作为测试,我编写了一个着色器将所有体素设置为一个常数值,但纹理根本没有修改。我如何使它工作? 计算着色器: #version 430 layou
我可以像这样用 JavFX 制作一个矩形: Rectangle node2 = RectangleBuilder.create() .x(-100) .
我在 iPhone 上遇到了 openGL 问题,我确信一定有一个简单的解决方案! 当我加载纹理并显示它时,我得到了很多我认为所谓的“色带”,其中颜色,特别是渐变上的颜色,似乎会自动“优化”。 只是为
假设我有一个域类 class Profile{ String name byte[] logo } 和一个 Controller : class ImageController {
我正在开发一款使用 SDL 的 2D 游戏。由于某些系统的 CPU 较弱而 GPU 较强,因此除了普通的 SDL/软件之外,我还有一个使用 OpenGL 的渲染器后端。 渲染器界面的简化版本如下所示:
我是一名优秀的程序员,十分优秀!