我想把纹理放在球体外面,我搜索一些链接
https://github.com/ejeinc/RajawaliCardboardExample
所有都将纹理放在球体内部。怎么做
我在球体内部做了纹理
public class SphereModel {
// Init variable value
private final int INVALID_STATE = -1;
int mProgram = INVALID_STATE;
int muMVPMatrixHandle = -1;
int muMMatrixHandle = -1;//
int maCameraHandle = -1; //
int maPositionHandle = -1; //
int maNormalHandle = -1; //
int maTexCoorHandle = -1; //
int maSunLightLocationHandle = -1;
int uDayTexHandle = -1;
String mVertexShader;
String mFragmentShader;
FloatBuffer mVertexBuffer;
FloatBuffer mTexCoorBuffer;
int vCount = 0;
float[] mvpM = new float[16];
float[] mM = new float[16];
public SphereModel(Resources r, float radius) {
initVertexData(radius);
initShader(r);
Matrix.setIdentityM(mvpM, 0);
Matrix.setIdentityM(mM, 0);
Matrix.translateM(mM, 0, 0, 0, 0);
}
public void initVertexData(float r) {
// ================begin============================
final float UNIT_SIZE = 0.5f;
ArrayList<Float> alVertix = new ArrayList<Float>();
final float angleSpan = 10f;
for (float vAngle = 90; vAngle > -90; vAngle = vAngle - angleSpan) {
for (float hAngle = 360; hAngle > 0; hAngle = hAngle - angleSpan) {
double xozLength = r * UNIT_SIZE
* Math.cos(Math.toRadians(vAngle));
float x1 = (float) (xozLength * Math
.cos(Math.toRadians(hAngle)));
float z1 = (float) (xozLength * Math
.sin(Math.toRadians(hAngle)));
float y1 = (float) (r * UNIT_SIZE * Math.sin(Math
.toRadians(vAngle)));
xozLength = r * UNIT_SIZE
* Math.cos(Math.toRadians(vAngle - angleSpan));
float x2 = (float) (xozLength * Math
.cos(Math.toRadians(hAngle)));
float z2 = (float) (xozLength * Math
.sin(Math.toRadians(hAngle)));
float y2 = (float) (r * UNIT_SIZE * Math.sin(Math
.toRadians(vAngle - angleSpan)));
xozLength = r * UNIT_SIZE
* Math.cos(Math.toRadians(vAngle - angleSpan));
float x3 = (float) (xozLength * Math.cos(Math.toRadians(hAngle
- angleSpan)));
float z3 = (float) (xozLength * Math.sin(Math.toRadians(hAngle
- angleSpan)));
float y3 = (float) (r * UNIT_SIZE * Math.sin(Math
.toRadians(vAngle - angleSpan)));
xozLength = r * UNIT_SIZE * Math.cos(Math.toRadians(vAngle));
float x4 = (float) (xozLength * Math.cos(Math.toRadians(hAngle
- angleSpan)));
float z4 = (float) (xozLength * Math.sin(Math.toRadians(hAngle
- angleSpan)));
float y4 = (float) (r * UNIT_SIZE * Math.sin(Math
.toRadians(vAngle)));
alVertix.add(x1);
alVertix.add(y1);
alVertix.add(z1);
alVertix.add(x2);
alVertix.add(y2);
alVertix.add(z2);
alVertix.add(x4);
alVertix.add(y4);
alVertix.add(z4);
alVertix.add(x4);
alVertix.add(y4);
alVertix.add(z4);
alVertix.add(x2);
alVertix.add(y2);
alVertix.add(z2);
alVertix.add(x3);
alVertix.add(y3);
alVertix.add(z3);
}
}
vCount = alVertix.size() / 3;
float vertices[] = new float[vCount * 3];
for (int i = 0; i < alVertix.size(); i++) {
vertices[i] = alVertix.get(i);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
float[] texCoor = generateTexCoor(
(int) (360 / angleSpan),
(int) (180 / angleSpan)
);
ByteBuffer llbb = ByteBuffer.allocateDirect(texCoor.length * 4);
llbb.order(ByteOrder.nativeOrder());
mTexCoorBuffer = llbb.asFloatBuffer();
mTexCoorBuffer.put(texCoor);
mTexCoorBuffer.position(0);
}
public void initShader(Resources r) {
mVertexShader = ShaderUtil.loadFromAssetsFile("vertex_tex_f.sh", r);
ShaderUtil.checkGlError("==ss==");
mFragmentShader = ShaderUtil.loadFromAssetsFile("frag_tex_f.sh", r);
ShaderUtil.checkGlError("==ss==");
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
maTexCoorHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoor");
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(Eye transform, int textureId) {
GLES20.glUseProgram(mProgram);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glFrontFace(GLES20.GL_CW);
if(ThunderConstant.MODE_CHOICE==1){
if(ThunderConstant.TYPE_CHOICE==0){
Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
}else if(ThunderConstant.TYPE_CHOICE==1){
Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
Matrix.translateM(mM, 0, 0, -1.5f, 0);
}else if(ThunderConstant.TYPE_CHOICE==2){
}
}else{
if(ThunderConstant.TYPE_CHOICE==0){
Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
}else if(ThunderConstant.TYPE_CHOICE==1){
Matrix.setLookAtM(mM, 0, 0, 0, 0, 0f, 0f, -10f, 0f, 1f, 0f);
Matrix.translateM(mM, 0, 0, -1.5f, 0);
}else if(ThunderConstant.TYPE_CHOICE==2){
}
}
Matrix.multiplyMM(mvpM, 0, transform.getEyeView(), 0, mM, 0);
Matrix.multiplyMM(mvpM, 0, transform.getPerspective(0.1f, 200f), 0, mvpM, 0);
if(PanoramaImageActivityNormalMode.isGestureControl){
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false,
MatrixState.getFinalMatrixOfFullImage(transform), 0);
}else{
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpM, 0);
}
GLES20.glVertexAttribPointer(
maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4,
mVertexBuffer);
GLES20.glVertexAttribPointer(
maTexCoorHandle, 2, GLES20.GL_FLOAT, false, 2 * 4,
mTexCoorBuffer);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
// GLES20.glEnableVertexAttribArray(maNormalHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
public float[] generateTexCoor(int bw, int bh) {
float[] result = new float[bw * bh * 6 * 2];
// float sizew=1.0f/bw;
// float sizeh=1.0f/bh;
float sizew = 1.0f / bw;
float sizeh = 1.0f / bh;
int c = 0;
for (int i = 0; i < bh; i++) {
for (int j = 0; j < bw; j++) {
float s = 1 - j * sizew;
float t = i * sizeh;
result[c++] = s;
result[c++] = t;
result[c++] = s;
result[c++] = t + sizeh;
result[c++] = s - sizew;
result[c++] = t;
//
result[c++] = s - sizew;
result[c++] = t;
result[c++] = s;
result[c++] = t + sizeh;
result[c++] = s - sizew;
result[c++] = t + sizeh;
}
}
return result;
}
/**
* recycle resource
*/
public void recyleRecource() {
if (mProgram != INVALID_STATE) {
GLES20.glDeleteProgram(mProgram);
mProgram = INVALID_STATE;
}
}
}
如何修改它使球体内部的纹理
答案 0 :(得分:1)
一种简单的方法(但不推荐)是去除背面剔除。 See Here
真正的问题在于如何表示纹理坐标和曲面法线。想想球体的哪一侧是正面,哪一面是背面。如果你想要球体外部的纹理,那么缠绕顺序,表面法线和纹理坐标需要反映出来。
根据您提供的代码示例,您需要更改此代码中的绕组顺序和U,V
for (c = 0; c <= stacks; c++) {
float u = (float) c / (float) stacks; // [0,1]
float theta2 = u * (float) (Math.PI * 2f); // [0,2PI]
pos.set(n);
pos.rotateY(theta2);
posFull.set(pos);
posFull.mulInPlace(dimension.x);
mesh.vertices.addVertex(posFull.x, posFull.y, posFull.z, pos.x, pos.y, pos.z, emissive.r, emissive.g, emissive.b, emissive.a, u, v);
}
想象一下在'mesh.vertices.addVertex'期间由此代码创建的三角形。对于每组三个顶点(每个三角形),您需要反转缠绕顺序,以便翻转三角形以呈现到外部。根据您使用的纹理,您可能还需要翻转传入的U,V坐标。
修改强> 我没有一个编辑器可以证明它,但你可能只需要反转for循环(向后迭代for循环)并以相反的顺序添加顶点以反转绕组。
像
这样的东西for (c = stacks-1; c >= 0; --c) {
...
}